You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2011/10/07 14:15:25 UTC

svn commit: r1180015 - in /cxf/trunk/services/sts/sts-core/src: main/java/org/apache/cxf/sts/operation/ main/java/org/apache/cxf/sts/token/realm/ main/java/org/apache/cxf/sts/token/validator/ test/java/org/apache/cxf/sts/operation/ test/java/org/apache...

Author: coheigea
Date: Fri Oct  7 12:15:25 2011
New Revision: 1180015

URL: http://svn.apache.org/viewvc?rev=1180015&view=rev
Log:
Add support to the STS for certificate constraints + pluggable realm retrieval on the validation side

Added:
    cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/CertConstraintsParser.java
    cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/SAMLRealmCodec.java
    cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/UsernameTokenRealmCodec.java
    cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomUsernameTokenRealmCodec.java
    cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/IssuerSAMLRealmCodec.java
Removed:
    cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateSamlRealmUnitTest.java
Modified:
    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/token/validator/SAMLTokenValidator.java
    cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java
    cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomIdentityMapper.java
    cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateTokenTransformationUnitTest.java
    cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorRealmTest.java
    cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorTest.java

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=1180015&r1=1180014&r2=1180015&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 Fri Oct  7 12:15:25 2011
@@ -135,12 +135,12 @@ public class TokenValidateOperation exte
             // Map the principal (if it exists)
             Principal responsePrincipal = tokenResponse.getPrincipal();
             if (responsePrincipal != null) {
-                String realm = providerParameters.getRealm();
-                String targetRealm = tokenResponse.getTokenRealm();
+                String targetRealm = providerParameters.getRealm();
+                String sourceRealm = tokenResponse.getTokenRealm();
                 IdentityMapper identityMapper = stsProperties.getIdentityMapper();
-                if (realm != null && !realm.equals(targetRealm) && identityMapper != null) {
+                if (sourceRealm != null && !sourceRealm.equals(targetRealm) && identityMapper != null) {
                     Principal targetPrincipal = 
-                        identityMapper.mapPrincipal(realm, responsePrincipal, targetRealm);
+                        identityMapper.mapPrincipal(sourceRealm, responsePrincipal, targetRealm);
                     providerParameters.setPrincipal(targetPrincipal);
                 } else {
                     providerParameters.setPrincipal(responsePrincipal);

Added: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/CertConstraintsParser.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/CertConstraintsParser.java?rev=1180015&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/CertConstraintsParser.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/CertConstraintsParser.java Fri Oct  7 12:15:25 2011
@@ -0,0 +1,93 @@
+/**
+ * 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.token.realm;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.apache.cxf.common.logging.LogUtils;
+
+/**
+ * This class provides the functionality to match a given X509Certificate against a list of
+ * regular expressions.
+ */
+public class CertConstraintsParser {
+    private static final Logger LOG = LogUtils.getL7dLogger(CertConstraintsParser.class);
+    
+    /**
+     * a collection of compiled regular expression patterns for the subject DN
+     */
+    private Collection<Pattern> subjectDNPatterns = new ArrayList<Pattern>();
+    
+    /**
+     * Set a list of Strings corresponding to regular expression constraints on the subject DN
+     * of a certificate
+     */
+    public void setSubjectConstraints(List<String> constraints) {
+        if (constraints != null) {
+            subjectDNPatterns = new ArrayList<Pattern>();
+            for (String constraint : constraints) {
+                try {
+                    subjectDNPatterns.add(Pattern.compile(constraint.trim()));
+                } catch (PatternSyntaxException ex) {
+                    LOG.severe(ex.getMessage());
+                    throw ex;
+                }
+            }
+        }
+    }
+    
+    /**
+     * @return      true if the certificate's SubjectDN matches the constraints defined in the
+     *              subject DNConstraints; false, otherwise. The certificate subject DN only
+     *              has to match ONE of the subject cert constraints (not all).
+     */
+    public boolean
+    matches(
+        final java.security.cert.X509Certificate cert
+    ) {
+        if (!subjectDNPatterns.isEmpty()) {
+            if (cert == null) {
+                LOG.fine("The certificate is null so no constraints matching was possible");
+                return false;
+            }
+            String subjectName = cert.getSubjectX500Principal().getName();
+            boolean subjectMatch = false;
+            for (Pattern subjectDNPattern : subjectDNPatterns) {
+                final Matcher matcher = subjectDNPattern.matcher(subjectName);
+                if (matcher.matches()) {
+                    LOG.fine("Subject DN " + subjectName + " matches with pattern " + subjectDNPattern);
+                    subjectMatch = true;
+                    break;
+                }
+            }
+            if (!subjectMatch) {
+                return false;
+            }
+        }
+        
+        return true;
+    }
+}

Added: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/SAMLRealmCodec.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/SAMLRealmCodec.java?rev=1180015&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/SAMLRealmCodec.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/SAMLRealmCodec.java Fri Oct  7 12:15:25 2011
@@ -0,0 +1,37 @@
+/**
+ * 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.token.realm;
+
+import org.apache.ws.security.saml.ext.AssertionWrapper;
+
+
+/**
+ * This interface defines a pluggable way to return a realm associated with a SAML Assertion.
+ */
+public interface SAMLRealmCodec {
+    
+    /**
+     * Get the realm associated with the AssertionWrapper parameter
+     * @param assertion a SAML Assertion wrapper object
+     * @return the realm associated with the AssertionWrapper parameter
+     */
+    String getRealmFromToken(AssertionWrapper assertion);
+    
+}

Added: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/UsernameTokenRealmCodec.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/UsernameTokenRealmCodec.java?rev=1180015&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/UsernameTokenRealmCodec.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/UsernameTokenRealmCodec.java Fri Oct  7 12:15:25 2011
@@ -0,0 +1,36 @@
+/**
+ * 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.token.realm;
+
+import org.apache.ws.security.message.token.UsernameToken;
+
+/**
+ * This interface defines a pluggable way to return a realm associated with a UsernameToken.
+ */
+public interface UsernameTokenRealmCodec {
+    
+    /**
+     * Get the realm associated with the UsernameToken parameter
+     * @param usernameToken a WSS4J UsernameToken object
+     * @return the realm associated with the UsernameToken parameter
+     */
+    String getRealmFromToken(UsernameToken usernameToken);
+    
+}

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=1180015&r1=1180014&r2=1180015&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 Fri Oct  7 12:15:25 2011
@@ -18,9 +18,9 @@
  */
 package org.apache.cxf.sts.token.validator;
 
+import java.security.cert.X509Certificate;
 import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -32,9 +32,9 @@ import org.apache.cxf.common.logging.Log
 import org.apache.cxf.sts.STSPropertiesMBean;
 import org.apache.cxf.sts.request.ReceivedToken;
 import org.apache.cxf.sts.request.TokenRequirements;
-import org.apache.cxf.sts.token.realm.SAMLRealm;
+import org.apache.cxf.sts.token.realm.CertConstraintsParser;
+import org.apache.cxf.sts.token.realm.SAMLRealmCodec;
 import org.apache.cxf.ws.security.tokenstore.SecurityToken;
-
 import org.apache.ws.security.SAMLTokenPrincipal;
 import org.apache.ws.security.WSConstants;
 import org.apache.ws.security.WSDocInfo;
@@ -57,7 +57,17 @@ public class SAMLTokenValidator implemen
     
     private Validator validator = new SignatureTrustValidator();
     
-    private Map<String, SAMLRealm> realmMap = new HashMap<String, SAMLRealm>();
+    private CertConstraintsParser certConstraints = new CertConstraintsParser();
+    
+    private SAMLRealmCodec samlRealmCodec;
+    
+    /**
+     * Set a list of Strings corresponding to regular expression constraints on the subject DN
+     * of a certificate that was used to sign a received Assertion
+     */
+    public void setSubjectConstraints(List<String> subjectConstraints) {
+        certConstraints.setSubjectConstraints(subjectConstraints);
+    }
     
     /**
      * Set the WSS4J Validator instance to use to validate the token.
@@ -68,6 +78,14 @@ public class SAMLTokenValidator implemen
     }
     
     /**
+     * Set the SAMLRealmCodec instance to use to return a realm from a validated token
+     * @param samlRealmCodec the SAMLRealmCodec instance to use to return a realm from a validated token
+     */
+    public void setSamlRealmCodec(SAMLRealmCodec samlRealmCodec) {
+        this.samlRealmCodec = samlRealmCodec;
+    }
+    
+    /**
      * Return true if this TokenValidator implementation is capable of validating the
      * ReceivedToken argument.
      */
@@ -77,13 +95,9 @@ public class SAMLTokenValidator implemen
     
     /**
      * Return true if this TokenValidator implementation is capable of validating the
-     * ReceivedToken argument.
+     * ReceivedToken argument. The realm is ignored in this Validator.
      */
     public boolean canHandleToken(ReceivedToken validateTarget, String realm) {
-        if (realm != null && !realmMap.containsKey(realm)) {
-            return false;
-        }
-        
         Object token = validateTarget.getToken();
         if (token instanceof Element) {
             Element tokenElement = (Element)token;
@@ -153,31 +167,27 @@ public class SAMLTokenValidator implemen
     
                 validator.validate(trustCredential, requestData);
 
-                // Finally check that the issuer is trusted
-                String trustedIssuer = null;
-                String assertionIssuer = assertion.getIssuerString();
-                for (String realm : realmMap.keySet()) {
-                    SAMLRealm samlRealm = realmMap.get(realm);
-                    if (samlRealm.getIssuer().equals(assertionIssuer)) {
-                        trustedIssuer = realm;
-                        break;
-                    }
-                }
-                if (trustedIssuer == null && assertionIssuer.equals(stsProperties.getIssuer())) {
-                    trustedIssuer = stsProperties.getIssuer();
+                // Finally check that subject DN of the signing certificate matches a known constraint
+                X509Certificate cert = null;
+                if (trustCredential.getCertificates() != null) {
+                    cert = trustCredential.getCertificates()[0];
                 }
-                if (trustedIssuer != null) {
-                    response.setValid(true);
-                    SAMLTokenPrincipal samlPrincipal = new SAMLTokenPrincipal(assertion);
-                    response.setPrincipal(samlPrincipal);
-                    response.setTokenRealm(trustedIssuer);
+                
+                if (!certConstraints.matches(cert)) {
+                    return response;
                 }
-            } else {
-                response.setValid(true);
-                SAMLTokenPrincipal samlPrincipal = new SAMLTokenPrincipal(assertion);
-                response.setPrincipal(samlPrincipal);
-                response.setTokenRealm(assertion.getIssuerString());
             }
+            
+            // Get the realm of the SAML token
+            String tokenRealm = null;
+            if (samlRealmCodec != null) {
+                tokenRealm = samlRealmCodec.getRealmFromToken(assertion);
+            }
+            
+            response.setValid(true);
+            SAMLTokenPrincipal samlPrincipal = new SAMLTokenPrincipal(assertion);
+            response.setPrincipal(samlPrincipal);
+            response.setTokenRealm(tokenRealm);
         } catch (WSSecurityException ex) {
             LOG.log(Level.WARNING, "", ex);
         }
@@ -185,20 +195,4 @@ public class SAMLTokenValidator implemen
         return response;
     }
     
-    /**
-     * Set the map of realm->SAMLRealm for this token provider
-     * @param realms the map of realm->SAMLRealm for this token provider
-     */
-    public void setRealmMap(Map<String, SAMLRealm> realms) {
-        this.realmMap = realms;
-    }
-    
-    /**
-     * Get the map of realm->SAMLRealm for this token provider
-     * @return the map of realm->SAMLRealm for this token provider
-     */
-    public Map<String, SAMLRealm> getRealmMap() {
-        return realmMap;
-    }
-    
 }

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=1180015&r1=1180014&r2=1180015&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 Fri Oct  7 12:15:25 2011
@@ -37,6 +37,7 @@ import org.apache.cxf.sts.QNameConstants
 import org.apache.cxf.sts.STSPropertiesMBean;
 import org.apache.cxf.sts.request.ReceivedToken;
 import org.apache.cxf.sts.request.TokenRequirements;
+import org.apache.cxf.sts.token.realm.UsernameTokenRealmCodec;
 
 import org.apache.cxf.ws.security.sts.provider.model.secext.UsernameTokenType;
 import org.apache.cxf.ws.security.tokenstore.SecurityToken;
@@ -60,6 +61,8 @@ public class UsernameTokenValidator impl
     
     private Validator validator = new org.apache.ws.security.validate.UsernameTokenValidator();
     
+    private UsernameTokenRealmCodec usernameTokenRealmCodec;
+    
     /**
      * Set the WSS4J Validator instance to use to validate the token.
      * @param validator the WSS4J Validator instance to use to validate the token
@@ -69,6 +72,15 @@ public class UsernameTokenValidator impl
     }
     
     /**
+     * Set the UsernameTokenRealmCodec instance to use to return a realm from a validated token
+     * @param usernameTokenRealmCodec the UsernameTokenRealmCodec instance to use to return a 
+     *                                realm from a validated token
+     */
+    public void setUsernameTokenRealmCodec(UsernameTokenRealmCodec usernameTokenRealmCodec) {
+        this.usernameTokenRealmCodec = usernameTokenRealmCodec;
+    }
+    
+    /**
      * Return true if this TokenValidator implementation is capable of validating the
      * ReceivedToken argument.
      */
@@ -115,6 +127,7 @@ public class UsernameTokenValidator impl
         // Turn the JAXB UsernameTokenType into a DOM Element for validation
         //
         UsernameTokenType usernameTokenType = (UsernameTokenType)validateTarget.getToken();
+        
         SecurityToken secToken = null;
         if (tokenParameters.getTokenStore() != null) {
             secToken = tokenParameters.getTokenStore().getToken(usernameTokenType.getId());
@@ -142,6 +155,7 @@ public class UsernameTokenValidator impl
         } else {
             usernameTokenElement = secToken.getToken();
         }
+        
         //
         // Validate the token
         //
@@ -154,7 +168,6 @@ public class UsernameTokenValidator impl
             if (ut.getPassword() == null) {
                 return response;
             }
-            
             if (secToken == null || (secToken.getAssociatedHash() != ut.hashCode())) {
                 Credential credential = new Credential();
                 credential.setUsernametoken(ut);
@@ -164,7 +177,15 @@ public class UsernameTokenValidator impl
                 createPrincipal(
                     ut.getName(), ut.getPassword(), ut.getPasswordType(), ut.getNonce(), ut.getCreated()
                 );
+            
+            // Get the realm of the UsernameToken
+            String tokenRealm = null;
+            if (usernameTokenRealmCodec != null) {
+                tokenRealm = usernameTokenRealmCodec.getRealmFromToken(ut);
+            }
+            
             response.setPrincipal(principal);
+            response.setTokenRealm(tokenRealm);
             response.setValid(true);
         } catch (WSSecurityException ex) {
             LOG.log(Level.WARNING, "", ex);

Modified: cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomIdentityMapper.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomIdentityMapper.java?rev=1180015&r1=1180014&r2=1180015&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomIdentityMapper.java (original)
+++ cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomIdentityMapper.java Fri Oct  7 12:15:25 2011
@@ -37,10 +37,10 @@ public class CustomIdentityMapper implem
      */
     public Principal mapPrincipal(String sourceRealm, Principal sourcePrincipal, String targetRealm) {
         if ("A".equals(sourceRealm)) {
-            String name = sourcePrincipal.getName().toLowerCase();
+            String name = sourcePrincipal.getName().toUpperCase();
             return new CustomTokenPrincipal(name);
         } else if ("B".equals(sourceRealm)) {
-            String name = sourcePrincipal.getName().toUpperCase();
+            String name = sourcePrincipal.getName().toLowerCase();
             return new CustomTokenPrincipal(name);
         }
         return null;

Added: cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomUsernameTokenRealmCodec.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomUsernameTokenRealmCodec.java?rev=1180015&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomUsernameTokenRealmCodec.java (added)
+++ cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomUsernameTokenRealmCodec.java Fri Oct  7 12:15:25 2011
@@ -0,0 +1,41 @@
+/**
+ * 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 org.apache.cxf.sts.token.realm.UsernameTokenRealmCodec;
+import org.apache.ws.security.message.token.UsernameToken;
+
+/**
+ * This class defines a pluggable way to return a realm associated with a UsernameToken.
+ */
+public class CustomUsernameTokenRealmCodec implements UsernameTokenRealmCodec {
+    
+    /**
+     * Get the realm associated with the UsernameToken parameter
+     * @param usernameToken a WSS4J UsernameToken object
+     * @return the realm associated with the UsernameToken parameter
+     */
+    public String getRealmFromToken(UsernameToken usernameToken) {
+        if ("alice".equals(usernameToken.getName())) {
+            return "A";
+        }
+        return null;
+    }
+    
+}

Modified: cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateTokenTransformationUnitTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateTokenTransformationUnitTest.java?rev=1180015&r1=1180014&r2=1180015&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateTokenTransformationUnitTest.java (original)
+++ cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateTokenTransformationUnitTest.java Fri Oct  7 12:15:25 2011
@@ -151,8 +151,8 @@ public class ValidateTokenTransformation
     }
     
     /**
-     * Test to successfully validate a UsernameToken in Realm "B" and transform it into a 
-     * SAML Assertion in Realm "A".
+     * Test to successfully validate a UsernameToken (which was issued in realm "A") and 
+     * transform it into a SAML Assertion in Realm "B".
      */
     @org.junit.Test
     public void testUsernameTokenTransformationRealm() throws Exception {
@@ -160,7 +160,9 @@ public class ValidateTokenTransformation
         
         // Add Token Validator
         List<TokenValidator> validatorList = new ArrayList<TokenValidator>();
-        validatorList.add(new UsernameTokenValidator());
+        UsernameTokenValidator validator = new UsernameTokenValidator();
+        validator.setUsernameTokenRealmCodec(new CustomUsernameTokenRealmCodec());
+        validatorList.add(validator);
         validateOperation.setTokenValidators(validatorList);
 
         // Add Token Provider

Added: cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/IssuerSAMLRealmCodec.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/IssuerSAMLRealmCodec.java?rev=1180015&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/IssuerSAMLRealmCodec.java (added)
+++ cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/IssuerSAMLRealmCodec.java Fri Oct  7 12:15:25 2011
@@ -0,0 +1,44 @@
+/**
+ * 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.token.validator;
+
+import org.apache.cxf.sts.token.realm.SAMLRealmCodec;
+import org.apache.ws.security.saml.ext.AssertionWrapper;
+
+
+/**
+ * This class returns a realm associated with a SAML Assertion depending on the issuer.
+ */
+public class IssuerSAMLRealmCodec implements SAMLRealmCodec {
+    
+    /**
+     * Get the realm associated with the AssertionWrapper parameter
+     * @param assertion a SAML Assertion wrapper object
+     * @return the realm associated with the AssertionWrapper parameter
+     */
+    public String getRealmFromToken(AssertionWrapper assertion) {
+        if ("A-Issuer".equals(assertion.getIssuerString())) {
+            return "A";
+        } else if ("B-Issuer".equals(assertion.getIssuerString())) {
+            return "B";
+        }
+        return null;
+    }
+    
+}

Modified: cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorRealmTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorRealmTest.java?rev=1180015&r1=1180014&r2=1180015&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorRealmTest.java (original)
+++ cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorRealmTest.java Fri Oct  7 12:15:25 2011
@@ -43,6 +43,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.realm.SAMLRealm;
+import org.apache.cxf.sts.token.realm.SAMLRealmCodec;
 import org.apache.ws.security.CustomTokenPrincipal;
 import org.apache.ws.security.WSConstants;
 import org.apache.ws.security.WSSecurityException;
@@ -50,18 +51,17 @@ import org.apache.ws.security.components
 import org.apache.ws.security.components.crypto.CryptoFactory;
 
 /**
- * Some unit tests for validating a SAML token via the SAMLTokenValidator in different realms.
+ * Some unit tests for validating a SAML token in different realms via the SAMLTokenValidator.
  */
 public class SAMLTokenValidatorRealmTest extends org.junit.Assert {
     
     /**
-     * Test a SAML 1.1 Assertion created in realm "A" and validated in realm "B".
+     * Test a SAML 1.1 Assertion created in realm "A".
      */
     @org.junit.Test
-    public void testDifferentRealms() throws Exception {
+    public void testRealmA() throws Exception {
         TokenValidator samlTokenValidator = new SAMLTokenValidator();
         TokenValidatorParameters validatorParameters = createValidatorParameters();
-        validatorParameters.setRealm("B");
         TokenRequirements tokenRequirements = validatorParameters.getTokenRequirements();
         
         // Create a ValidateTarget consisting of a SAML Assertion
@@ -75,17 +75,16 @@ public class SAMLTokenValidatorRealmTest
         ReceivedToken validateTarget = new ReceivedToken(samlToken);
         tokenRequirements.setValidateTarget(validateTarget);
         
-        // Token Validation should fail as the TokenValidator doesn't know about the realm "A"
+        // Validate the token - no realm is returned
         TokenValidatorResponse validatorResponse = 
             samlTokenValidator.validateToken(validatorParameters);
         assertTrue(validatorResponse != null);
-        assertFalse(validatorResponse.isValid());
+        assertTrue(validatorResponse.isValid());
+        assertNull(validatorResponse.getTokenRealm());
 
-        // Now set the realms on the Validator and try to validate the token again
-        Map<String, SAMLRealm> samlRealms = getSamlRealms();
-        ((SAMLTokenValidator)samlTokenValidator).setRealmMap(samlRealms);
-        
-        assertTrue(samlTokenValidator.canHandleToken(validateTarget, "B"));
+        // Now set the SAMLRealmCodec implementation on the Validator
+        SAMLRealmCodec samlRealmCodec = new IssuerSAMLRealmCodec();
+        ((SAMLTokenValidator)samlTokenValidator).setSamlRealmCodec(samlRealmCodec);
         
         validatorResponse = samlTokenValidator.validateToken(validatorParameters);
         assertTrue(validatorResponse != null);
@@ -96,6 +95,46 @@ public class SAMLTokenValidatorRealmTest
         assertTrue(principal != null && principal.getName() != null);
     }
     
+    /**
+     * Test a SAML 1.1 Assertion created in realm "B".
+     */
+    @org.junit.Test
+    public void testRealmB() throws Exception {
+        TokenValidator samlTokenValidator = new SAMLTokenValidator();
+        TokenValidatorParameters validatorParameters = createValidatorParameters();
+        TokenRequirements tokenRequirements = validatorParameters.getTokenRequirements();
+        
+        // Create a ValidateTarget consisting of a SAML Assertion
+        Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties());
+        CallbackHandler callbackHandler = new PasswordCallbackHandler();
+        Element samlToken = 
+            createSAMLAssertion(WSConstants.WSS_SAML_TOKEN_TYPE, crypto, "mystskey", callbackHandler, "B");
+        Document doc = samlToken.getOwnerDocument();
+        samlToken = (Element)doc.appendChild(samlToken);
+        
+        ReceivedToken validateTarget = new ReceivedToken(samlToken);
+        tokenRequirements.setValidateTarget(validateTarget);
+        
+        // Validate the token - no realm is returned
+        TokenValidatorResponse validatorResponse = 
+            samlTokenValidator.validateToken(validatorParameters);
+        assertTrue(validatorResponse != null);
+        assertTrue(validatorResponse.isValid());
+        assertNull(validatorResponse.getTokenRealm());
+
+        // Now set the SAMLRealmCodec implementation on the Validator
+        SAMLRealmCodec samlRealmCodec = new IssuerSAMLRealmCodec();
+        ((SAMLTokenValidator)samlTokenValidator).setSamlRealmCodec(samlRealmCodec);
+        
+        validatorResponse = samlTokenValidator.validateToken(validatorParameters);
+        assertTrue(validatorResponse != null);
+        assertTrue(validatorResponse.isValid());
+        assertTrue(validatorResponse.getTokenRealm().equals("B"));
+            
+        Principal principal = validatorResponse.getPrincipal();
+        assertTrue(principal != null && principal.getName() != null);
+    }
+    
     private TokenValidatorParameters createValidatorParameters() throws WSSecurityException {
         TokenValidatorParameters parameters = new TokenValidatorParameters();
         

Modified: cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorTest.java?rev=1180015&r1=1180014&r2=1180015&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorTest.java (original)
+++ cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorTest.java Fri Oct  7 12:15:25 2011
@@ -20,6 +20,8 @@ package org.apache.cxf.sts.token.validat
 
 import java.io.IOException;
 import java.security.Principal;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Properties;
 
 import javax.security.auth.callback.Callback;
@@ -129,19 +131,19 @@ public class SAMLTokenValidatorTest exte
     }
     
     /**
-     * Test a SAML 1.1 Assertion with an invalid issuer
+     * Test a SAML 1.1 Assertion with an invalid signature
      */
     @org.junit.Test
-    public void testInvalidIssuerSAML1Assertion() throws Exception {
+    public void testInvalidSignatureSAML1Assertion() throws Exception {
         TokenValidator samlTokenValidator = new SAMLTokenValidator();
         TokenValidatorParameters validatorParameters = createValidatorParameters();
         TokenRequirements tokenRequirements = validatorParameters.getTokenRequirements();
         
         // Create a ValidateTarget consisting of a SAML Assertion
-        Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties());
-        CallbackHandler callbackHandler = new PasswordCallbackHandler();
+        Crypto crypto = CryptoFactory.getInstance(getEveCryptoProperties());
+        CallbackHandler callbackHandler = new EveCallbackHandler();
         Element samlToken = 
-            createSAMLAssertion(WSConstants.WSS_SAML_TOKEN_TYPE, crypto, "mystskey", callbackHandler);
+            createSAMLAssertion(WSConstants.WSS_SAML_TOKEN_TYPE, crypto, "eve", callbackHandler);
         Document doc = samlToken.getOwnerDocument();
         samlToken = (Element)doc.appendChild(samlToken);
         
@@ -152,44 +154,7 @@ public class SAMLTokenValidatorTest exte
         
         // Set tokenstore to null so that issued token is not found in the cache
         validatorParameters.setTokenStore(null);
-        
-        // Change the issuer and so validation should fail
-        validatorParameters.getStsProperties().setIssuer("NewSTS");
-        
-        TokenValidatorResponse validatorResponse = 
-            samlTokenValidator.validateToken(validatorParameters);
-        assertTrue(validatorResponse != null);
-        assertFalse(validatorResponse.isValid());
-    }
-    
-    /**
-     * Test a SAML 2 Assertion with an invalid issuer
-     */
-    @org.junit.Test
-    public void testInvalidIssuerSAML2Assertion() throws Exception {
-        TokenValidator samlTokenValidator = new SAMLTokenValidator();
-        TokenValidatorParameters validatorParameters = createValidatorParameters();
-        TokenRequirements tokenRequirements = validatorParameters.getTokenRequirements();
-        
-        // Create a ValidateTarget consisting of a SAML Assertion
-        Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties());
-        CallbackHandler callbackHandler = new PasswordCallbackHandler();
-        Element samlToken = 
-            createSAMLAssertion(WSConstants.WSS_SAML2_TOKEN_TYPE, crypto, "mystskey", callbackHandler);
-        Document doc = samlToken.getOwnerDocument();
-        samlToken = (Element)doc.appendChild(samlToken);
-        
-        ReceivedToken validateTarget = new ReceivedToken(samlToken);
-        tokenRequirements.setValidateTarget(validateTarget);
-        
-        assertTrue(samlTokenValidator.canHandleToken(validateTarget));
- 
-        // Set tokenstore to null so that issued token is not found in the cache
-        validatorParameters.setTokenStore(null);
 
-        // Change the issuer and so validation should fail
-        validatorParameters.getStsProperties().setIssuer("NewSTS");
-        
         TokenValidatorResponse validatorResponse = 
             samlTokenValidator.validateToken(validatorParameters);
         assertTrue(validatorResponse != null);
@@ -197,10 +162,10 @@ public class SAMLTokenValidatorTest exte
     }
     
     /**
-     * Test a SAML 1.1 Assertion with an invalid signature
+     * Test a SAML 2 Assertion with an invalid signature
      */
     @org.junit.Test
-    public void testInvalidSignatureSAML1Assertion() throws Exception {
+    public void testInvalidSignatureSAML2Assertion() throws Exception {
         TokenValidator samlTokenValidator = new SAMLTokenValidator();
         TokenValidatorParameters validatorParameters = createValidatorParameters();
         TokenRequirements tokenRequirements = validatorParameters.getTokenRequirements();
@@ -209,7 +174,7 @@ public class SAMLTokenValidatorTest exte
         Crypto crypto = CryptoFactory.getInstance(getEveCryptoProperties());
         CallbackHandler callbackHandler = new EveCallbackHandler();
         Element samlToken = 
-            createSAMLAssertion(WSConstants.WSS_SAML_TOKEN_TYPE, crypto, "eve", callbackHandler);
+            createSAMLAssertion(WSConstants.WSS_SAML2_TOKEN_TYPE, crypto, "eve", callbackHandler);
         Document doc = samlToken.getOwnerDocument();
         samlToken = (Element)doc.appendChild(samlToken);
         
@@ -228,19 +193,20 @@ public class SAMLTokenValidatorTest exte
     }
     
     /**
-     * Test a SAML 2 Assertion with an invalid signature
+     * Test a SAML 1.1 Assertion using Certificate Constraints 
      */
     @org.junit.Test
-    public void testInvalidSignatureSAML2Assertion() throws Exception {
+    public void testSAML1AssertionCertConstraints() throws Exception {
         TokenValidator samlTokenValidator = new SAMLTokenValidator();
         TokenValidatorParameters validatorParameters = createValidatorParameters();
         TokenRequirements tokenRequirements = validatorParameters.getTokenRequirements();
+        validatorParameters.setTokenStore(null);
         
         // Create a ValidateTarget consisting of a SAML Assertion
-        Crypto crypto = CryptoFactory.getInstance(getEveCryptoProperties());
-        CallbackHandler callbackHandler = new EveCallbackHandler();
+        Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties());
+        CallbackHandler callbackHandler = new PasswordCallbackHandler();
         Element samlToken = 
-            createSAMLAssertion(WSConstants.WSS_SAML2_TOKEN_TYPE, crypto, "eve", callbackHandler);
+            createSAMLAssertion(WSConstants.WSS_SAML_TOKEN_TYPE, crypto, "mystskey", callbackHandler);
         Document doc = samlToken.getOwnerDocument();
         samlToken = (Element)doc.appendChild(samlToken);
         
@@ -248,13 +214,21 @@ public class SAMLTokenValidatorTest exte
         tokenRequirements.setValidateTarget(validateTarget);
         
         assertTrue(samlTokenValidator.canHandleToken(validateTarget));
+        List<String> certConstraints = new ArrayList<String>();
+        certConstraints.add("XYZ");
+        certConstraints.add(".*CN=www.sts.com.*");
+        ((SAMLTokenValidator)samlTokenValidator).setSubjectConstraints(certConstraints);
         
-        // Set tokenstore to null so that issued token is not found in the cache
-        validatorParameters.setTokenStore(null);
-
         TokenValidatorResponse validatorResponse = 
             samlTokenValidator.validateToken(validatorParameters);
         assertTrue(validatorResponse != null);
+        assertTrue(validatorResponse.isValid());
+        
+        certConstraints.clear();
+        certConstraints.add("XYZ");
+        ((SAMLTokenValidator)samlTokenValidator).setSubjectConstraints(certConstraints);
+        validatorResponse = samlTokenValidator.validateToken(validatorParameters);
+        assertTrue(validatorResponse != null);
         assertFalse(validatorResponse.isValid());
     }