You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by ow...@apache.org on 2013/05/30 22:55:45 UTC

svn commit: r1488009 - in /cxf/branches/2.7.x-fixes/services/sts/sts-core/src: main/java/org/apache/cxf/sts/claims/ main/java/org/apache/cxf/sts/token/realm/ test/java/org/apache/cxf/sts/common/ test/java/org/apache/cxf/sts/token/realm/

Author: owulff
Date: Thu May 30 20:55:45 2013
New Revision: 1488009

URL: http://svn.apache.org/r1488009
Log:
[CXF-5039] IdentityMapping support in ClaimsManager

Added:
    cxf/branches/2.7.x-fixes/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/RealmSupport.java
    cxf/branches/2.7.x-fixes/services/sts/sts-core/src/test/java/org/apache/cxf/sts/common/RealmSupportClaimsHandler.java
    cxf/branches/2.7.x-fixes/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/realm/
    cxf/branches/2.7.x-fixes/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/realm/RealmSupportTest.java
Modified:
    cxf/branches/2.7.x-fixes/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/ClaimsManager.java
    cxf/branches/2.7.x-fixes/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/LdapClaimsHandler.java
    cxf/branches/2.7.x-fixes/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/LdapGroupClaimsHandler.java

Modified: cxf/branches/2.7.x-fixes/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/ClaimsManager.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/ClaimsManager.java?rev=1488009&r1=1488008&r2=1488009&view=diff
==============================================================================
--- cxf/branches/2.7.x-fixes/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/ClaimsManager.java (original)
+++ cxf/branches/2.7.x-fixes/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/ClaimsManager.java Thu May 30 20:55:45 2013
@@ -21,6 +21,7 @@ package org.apache.cxf.sts.claims;
 
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.security.Principal;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -30,6 +31,8 @@ import java.util.logging.Logger;
 import org.w3c.dom.Element;
 
 import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.sts.IdentityMapper;
+import org.apache.cxf.sts.token.realm.RealmSupport;
 import org.apache.cxf.sts.token.realm.Relationship;
 import org.apache.cxf.ws.security.sts.provider.STSException;
 import org.apache.ws.security.saml.ext.AssertionWrapper;
@@ -48,6 +51,16 @@ public class ClaimsManager {
     private List<ClaimsHandler> claimHandlers;
     private List<URI> supportedClaimTypes = new ArrayList<URI>();
     private boolean stopProcessingOnException = true;
+    private IdentityMapper identityMapper;
+    
+
+    public IdentityMapper getIdentityMapper() {
+        return identityMapper;
+    }
+
+    public void setIdentityMapper(IdentityMapper identityMapper) {
+        this.identityMapper = identityMapper;
+    }
 
     public boolean isStopProcessingOnException() {
         return stopProcessingOnException;
@@ -124,37 +137,102 @@ public class ClaimsManager {
             relationship = (Relationship)parameters.getAdditionalProperties().get(
                     Relationship.class.getName());
         }
-
+        
+        if (claims == null || claims.size() == 0) {
+            return null;
+        }
         if (relationship == null || relationship.getType().equals(Relationship.FED_TYPE_IDENTITY)) {
             // Federate identity. Identity already mapped.
             // Call all configured claims handlers to retrieve the required claims
-            if (claimHandlers != null && claimHandlers.size() > 0 && claims != null && claims.size() > 0) {
-                ClaimCollection returnCollection = new ClaimCollection();
-                for (ClaimsHandler handler : claimHandlers) {
-                    RequestClaimCollection supportedClaims = 
-                            filterHandlerClaims(claims, handler.getSupportedClaimTypes());
-                    if (supportedClaims.isEmpty()) {
+            if (claimHandlers == null || claimHandlers.size() == 0) {
+                return null;
+            }
+            Principal originalPrincipal = parameters.getPrincipal();
+            ClaimCollection returnCollection = new ClaimCollection();
+            for (ClaimsHandler handler : claimHandlers) {
+                
+                RequestClaimCollection supportedClaims = 
+                    filterHandlerClaims(claims, handler.getSupportedClaimTypes());
+                if (supportedClaims.isEmpty()) {
+                    continue;
+                }
+                
+                if (handler instanceof RealmSupport) {
+                    RealmSupport handlerRealmSupport = (RealmSupport)handler;
+                    // Check whether the handler supports the current realm
+                    if (handlerRealmSupport.getSupportedRealms() != null
+                            && handlerRealmSupport.getSupportedRealms().size() > 0
+                            && handlerRealmSupport.getSupportedRealms().indexOf(parameters.getRealm()) == -1) {
+                        if (LOG.isLoggable(Level.FINER)) {
+                            LOG.finer("Handler '" + handler.getClass().getName() + "' doesn't support"
+                                    + " realm '" + parameters.getRealm()  + "'");
+                        }
                         continue;
                     }
                     
-                    ClaimCollection claimCollection = null;
-                    try {
-                        claimCollection = handler.retrieveClaimValues(claims, parameters);
-                    } catch (RuntimeException ex) {
-                        LOG.log(Level.INFO, "Failed retrieving claims from ClaimsHandler "
-                                + handler.getClass().getName(), ex);
-                        if (this.isStopProcessingOnException()) {
-                            throw ex;
+                    // If handler realm is configured and different from current realm
+                    // do an identity mapping
+                    if (handlerRealmSupport.getHandlerRealm() != null
+                            && !handlerRealmSupport.getHandlerRealm().equalsIgnoreCase(parameters.getRealm())) {
+                        Principal targetPrincipal = null;
+                        try {
+                            if (LOG.isLoggable(Level.FINE)) {
+                                LOG.fine("Mapping user '" + parameters.getPrincipal().getName()
+                                        + "' [" + parameters.getRealm() + "] to realm '"
+                                        + handlerRealmSupport.getHandlerRealm() + "'");
+                            }
+                            targetPrincipal = doMapping(parameters.getRealm(), parameters.getPrincipal(),
+                                    handlerRealmSupport.getHandlerRealm());
+                        } catch (Exception ex) {
+                            LOG.log(Level.WARNING, "Failed to map user '" + parameters.getPrincipal().getName()
+                                    + "' [" + parameters.getRealm() + "] to realm '"
+                                    + handlerRealmSupport.getHandlerRealm() + "'", ex);
+                            throw new STSException("Failed to map user for claims handler",
+                                    STSException.REQUEST_FAILED);
+                        }
+                        
+                        if (targetPrincipal == null) {
+                            LOG.log(Level.WARNING, "Null. Failed to map user '" + parameters.getPrincipal().getName()
+                                    + "' [" + parameters.getRealm() + "] to realm '"
+                                    + handlerRealmSupport.getHandlerRealm() + "'");
+                            throw new STSException("Failed to map user for claims handler",
+                                    STSException.REQUEST_FAILED);
+                        }
+                        if (LOG.isLoggable(Level.INFO)) {
+                            LOG.info("Principal '" + targetPrincipal.getName()
+                                    + "' passed to handler '" + handler.getClass().getName() + "'");
+                        }
+                        parameters.setPrincipal(targetPrincipal);
+                    } else {
+                        if (LOG.isLoggable(Level.FINER)) {
+                            LOG.finer("Handler '" + handler.getClass().getName() + "' doesn't require"
+                                    + " identity mapping '" + parameters.getRealm()  + "'");
                         }
+                        
                     }
-                    
-                    if (claimCollection != null && claimCollection.size() != 0) {
-                        returnCollection.addAll(claimCollection);
+                }
+                
+                ClaimCollection claimCollection = null;
+                try {
+                    claimCollection = handler.retrieveClaimValues(supportedClaims, parameters);
+                } catch (RuntimeException ex) {
+                    LOG.log(Level.INFO, "Failed retrieving claims from ClaimsHandler "
+                            + handler.getClass().getName(), ex);
+                    if (this.isStopProcessingOnException()) {
+                        throw ex;
                     }
+                } finally {
+                    // set original principal again, otherwise wrong principal passed to next claim handler in the list
+                    // if no mapping required or wrong source principal used for next identity mapping
+                    parameters.setPrincipal(originalPrincipal);
+                }
+                
+                if (claimCollection != null && claimCollection.size() != 0) {
+                    returnCollection.addAll(claimCollection);
                 }
-                validateClaimValues(claims, returnCollection);
-                return returnCollection;
             }
+            validateClaimValues(claims, returnCollection);
+            return returnCollection;
             
         } else {
             // Federate claims
@@ -184,7 +262,6 @@ public class ClaimsManager {
             return targetClaims;
         }
 
-        return null;
     }
 
     private RequestClaimCollection filterHandlerClaims(RequestClaimCollection claims,
@@ -357,5 +434,12 @@ public class ClaimsManager {
         
         return mergedClaims;
     }
+    
+    
+    protected Principal doMapping(String sourceRealm, Principal sourcePrincipal, String targetRealm) {
+        return this.identityMapper.mapPrincipal(
+                sourceRealm, sourcePrincipal, targetRealm);
+        
+    }
 
 }

Modified: cxf/branches/2.7.x-fixes/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/LdapClaimsHandler.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/LdapClaimsHandler.java?rev=1488009&r1=1488008&r2=1488009&view=diff
==============================================================================
--- cxf/branches/2.7.x-fixes/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/LdapClaimsHandler.java (original)
+++ cxf/branches/2.7.x-fixes/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/LdapClaimsHandler.java Thu May 30 20:55:45 2013
@@ -38,10 +38,11 @@ import javax.security.auth.x500.X500Prin
 
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.sts.token.realm.RealmSupport;
 import org.springframework.ldap.core.AttributesMapper;
 import org.springframework.ldap.core.LdapTemplate;
 
-public class LdapClaimsHandler implements ClaimsHandler {
+public class LdapClaimsHandler implements ClaimsHandler, RealmSupport {
 
     private static final Logger LOG = LogUtils.getL7dLogger(LdapClaimsHandler.class);
 
@@ -52,8 +53,18 @@ public class LdapClaimsHandler implement
     private boolean x500FilterEnabled = true;
     private String objectClass = "person";
     private String userNameAttribute = "cn";
+    private List<String> supportedRealms;
+    private String realm;
     
     
+    public void setSupportedRealms(List<String> supportedRealms) {
+        this.supportedRealms = supportedRealms;
+    }
+
+    public void setRealm(String realm) {
+        this.realm = realm;
+    }
+    
     public String getObjectClass() {
         return objectClass;
     }
@@ -257,7 +268,15 @@ public class LdapClaimsHandler implement
         return claimsColl;
     }
 
-    
+    @Override
+    public List<String> getSupportedRealms() {
+        return supportedRealms;
+    }
+
+    @Override
+    public String getHandlerRealm() {
+        return realm;
+    }  
 
 }
 

Modified: cxf/branches/2.7.x-fixes/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/LdapGroupClaimsHandler.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/LdapGroupClaimsHandler.java?rev=1488009&r1=1488008&r2=1488009&view=diff
==============================================================================
--- cxf/branches/2.7.x-fixes/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/LdapGroupClaimsHandler.java (original)
+++ cxf/branches/2.7.x-fixes/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/LdapGroupClaimsHandler.java Thu May 30 20:55:45 2013
@@ -34,9 +34,10 @@ import javax.security.auth.kerberos.Kerb
 import javax.security.auth.x500.X500Principal;
 
 import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.sts.token.realm.RealmSupport;
 import org.springframework.ldap.core.LdapTemplate;
 
-public class LdapGroupClaimsHandler implements ClaimsHandler {
+public class LdapGroupClaimsHandler implements ClaimsHandler, RealmSupport {
 
     private static final Logger LOG = LogUtils.getL7dLogger(LdapGroupClaimsHandler.class);
 
@@ -55,8 +56,18 @@ public class LdapGroupClaimsHandler impl
     private String groupNameScopedFilter = SCOPE + "_" + ROLE;
     private Map<String, String> appliesToScopeMapping;
     private boolean useFullGroupNameAsValue;
+    private List<String> supportedRealms;
+    private String realm;
     
     
+    public void setSupportedRealms(List<String> supportedRealms) {
+        this.supportedRealms = supportedRealms;
+    }
+
+    public void setRealm(String realm) {
+        this.realm = realm;
+    }    
+    
     public boolean isUseFullGroupNameAsValue() {
         return useFullGroupNameAsValue;
     }
@@ -304,6 +315,16 @@ public class LdapGroupClaimsHandler impl
 
         return claimsColl;
     }
+    
+    @Override
+    public List<String> getSupportedRealms() {
+        return supportedRealms;
+    }
+
+    @Override
+    public String getHandlerRealm() {
+        return realm;
+    }  
 
     private String parseRole(String group, String filter) {
         int roleStart = filter.indexOf(ROLE);

Added: cxf/branches/2.7.x-fixes/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/RealmSupport.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/RealmSupport.java?rev=1488009&view=auto
==============================================================================
--- cxf/branches/2.7.x-fixes/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/RealmSupport.java (added)
+++ cxf/branches/2.7.x-fixes/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/RealmSupport.java Thu May 30 20:55:45 2013
@@ -0,0 +1,34 @@
+/**
+ * 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.List;
+
+/**
+ * 
+ */
+public interface RealmSupport {
+
+    List<String> getSupportedRealms();
+
+    String getHandlerRealm();
+
+}
+ 
\ No newline at end of file

Added: cxf/branches/2.7.x-fixes/services/sts/sts-core/src/test/java/org/apache/cxf/sts/common/RealmSupportClaimsHandler.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/sts/sts-core/src/test/java/org/apache/cxf/sts/common/RealmSupportClaimsHandler.java?rev=1488009&view=auto
==============================================================================
--- cxf/branches/2.7.x-fixes/services/sts/sts-core/src/test/java/org/apache/cxf/sts/common/RealmSupportClaimsHandler.java (added)
+++ cxf/branches/2.7.x-fixes/services/sts/sts-core/src/test/java/org/apache/cxf/sts/common/RealmSupportClaimsHandler.java Thu May 30 20:55:45 2013
@@ -0,0 +1,104 @@
+/**
+ * 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.common;
+
+import java.net.URI;
+import java.util.List;
+
+import org.apache.cxf.sts.claims.Claim;
+import org.apache.cxf.sts.claims.ClaimCollection;
+import org.apache.cxf.sts.claims.ClaimsHandler;
+import org.apache.cxf.sts.claims.ClaimsParameters;
+import org.apache.cxf.sts.claims.RequestClaim;
+import org.apache.cxf.sts.claims.RequestClaimCollection;
+import org.apache.cxf.sts.token.realm.RealmSupport;
+import org.junit.Assert;
+
+/**
+ * A custom ClaimsHandler implementation for use in the tests.
+ */
+public class RealmSupportClaimsHandler implements ClaimsHandler, RealmSupport {
+    
+    private List<String> supportedRealms;
+    private String realm;
+    private List<URI> supportedClaimTypes;
+       
+   
+    public void setSupportedRealms(List<String> supportedRealms) {
+        this.supportedRealms = supportedRealms;
+    }
+
+    public void setRealm(String realm) {
+        this.realm = realm;
+    }
+    
+
+    public List<URI> getSupportedClaimTypes() {
+        return supportedClaimTypes;
+    }
+    
+    public void setSupportedClaimTypes(List<URI> supportedClaimTypes) {
+        this.supportedClaimTypes = supportedClaimTypes;
+    }
+    
+    public ClaimCollection retrieveClaimValues(
+            RequestClaimCollection claims, ClaimsParameters parameters) {
+        
+        if ("A".equals(realm)) {
+            Assert.assertEquals("ClaimHandler in realm A. Alice username must be 'alice'",
+                    "alice", parameters.getPrincipal().getName());
+        }
+        
+        if ("B".equals(realm)) {
+            Assert.assertEquals("ClaimHandler in realm B. Alice username must be 'ALICE'",
+                    "ALICE", parameters.getPrincipal().getName());
+        }
+        
+        if (supportedRealms != null && !supportedRealms.contains(parameters.getRealm())) {
+            Assert.fail("ClaimHandler must not be called. Source realm '" + parameters.getRealm()
+                    + "' not in supportedRealm list: " + supportedRealms);
+        }
+        
+        if (claims != null && claims.size() > 0) {
+            ClaimCollection claimCollection = new ClaimCollection();
+            for (RequestClaim requestClaim : claims) {
+                if (getSupportedClaimTypes().indexOf(requestClaim.getClaimType()) != -1) {
+                    Claim claim = new Claim();
+                    claim.setClaimType(requestClaim.getClaimType());
+                    claim.addValue("Value_" + requestClaim.getClaimType());
+                    claimCollection.add(claim);
+                }
+            }
+            return claimCollection;
+        }
+        
+        return null;
+    }
+
+    @Override
+    public List<String> getSupportedRealms() {
+        return supportedRealms;
+    }
+
+    @Override
+    public String getHandlerRealm() {
+        return realm;
+    }
+        
+}

Added: cxf/branches/2.7.x-fixes/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/realm/RealmSupportTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/realm/RealmSupportTest.java?rev=1488009&view=auto
==============================================================================
--- cxf/branches/2.7.x-fixes/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/realm/RealmSupportTest.java (added)
+++ cxf/branches/2.7.x-fixes/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/realm/RealmSupportTest.java Thu May 30 20:55:45 2013
@@ -0,0 +1,205 @@
+/**
+ * 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.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.cxf.sts.claims.ClaimCollection;
+import org.apache.cxf.sts.claims.ClaimsHandler;
+import org.apache.cxf.sts.claims.ClaimsManager;
+import org.apache.cxf.sts.claims.ClaimsParameters;
+import org.apache.cxf.sts.claims.RequestClaim;
+import org.apache.cxf.sts.claims.RequestClaimCollection;
+import org.apache.cxf.sts.common.RealmSupportClaimsHandler;
+import org.apache.cxf.sts.operation.CustomIdentityMapper;
+import org.apache.wss4j.common.principal.CustomTokenPrincipal;
+import org.junit.Assert;
+
+public class RealmSupportTest extends org.junit.Assert {
+
+    
+    @org.junit.Test
+    public void testIdentityMappingRealmA2B() throws Exception {
+        
+        ClaimsManager claimsManager = new ClaimsManager();
+        
+        claimsManager.setIdentityMapper(new CustomIdentityMapper());
+        
+        RealmSupportClaimsHandler realmAHandler = new RealmSupportClaimsHandler();
+        realmAHandler.setRealm("A");
+        realmAHandler.setSupportedClaimTypes(Collections.singletonList(URI.create("Claim-A")));
+        
+        RealmSupportClaimsHandler realmBHandler = new RealmSupportClaimsHandler();
+        realmBHandler.setRealm("B");
+        realmBHandler.setSupportedClaimTypes(Collections.singletonList(URI.create("Claim-B")));
+        
+        RealmSupportClaimsHandler realmCHandler = new RealmSupportClaimsHandler();
+        realmCHandler.setRealm("B");
+        realmCHandler.setSupportedClaimTypes(Collections.singletonList(URI.create("Claim-C")));
+        
+        List<ClaimsHandler> claimHandlers = new ArrayList<ClaimsHandler>();
+        claimHandlers.add(realmAHandler);
+        claimHandlers.add(realmBHandler);
+        claimHandlers.add(realmCHandler);
+        claimsManager.setClaimHandlers(Collections.unmodifiableList(claimHandlers));
+        
+        RequestClaimCollection requestedClaims = createRequestClaimCollection();
+        
+        ClaimsParameters parameters = new ClaimsParameters();
+        parameters.setRealm("A");
+        parameters.setPrincipal(new CustomTokenPrincipal("alice"));
+        ClaimCollection claims = claimsManager.retrieveClaimValues(requestedClaims, parameters);
+        Assert.assertEquals("Number of claims incorrect", 3, claims.size());
+    }
+    
+    @org.junit.Test
+    public void testIdentityMappingRealmB2A() throws Exception {
+        
+        ClaimsManager claimsManager = new ClaimsManager();
+        
+        claimsManager.setIdentityMapper(new CustomIdentityMapper());
+        
+        RealmSupportClaimsHandler realmAHandler = new RealmSupportClaimsHandler();
+        realmAHandler.setRealm("A");
+        realmAHandler.setSupportedClaimTypes(Collections.singletonList(URI.create("Claim-A")));
+        
+        RealmSupportClaimsHandler realmBHandler = new RealmSupportClaimsHandler();
+        realmBHandler.setRealm("B");
+        realmBHandler.setSupportedClaimTypes(Collections.singletonList(URI.create("Claim-B")));
+        
+        RealmSupportClaimsHandler realmCHandler = new RealmSupportClaimsHandler();
+        realmCHandler.setRealm("B");
+        realmCHandler.setSupportedClaimTypes(Collections.singletonList(URI.create("Claim-C")));
+        
+        List<ClaimsHandler> claimHandlers = new ArrayList<ClaimsHandler>();
+        claimHandlers.add(realmAHandler);
+        claimHandlers.add(realmBHandler);
+        claimHandlers.add(realmCHandler);
+        claimsManager.setClaimHandlers(Collections.unmodifiableList(claimHandlers));
+        
+        RequestClaimCollection requestedClaims = createRequestClaimCollection();
+        
+        ClaimsParameters parameters = new ClaimsParameters();
+        parameters.setRealm("B");
+        parameters.setPrincipal(new CustomTokenPrincipal("ALICE"));
+        ClaimCollection claims = claimsManager.retrieveClaimValues(requestedClaims, parameters);
+        Assert.assertEquals("Number of claims incorrect", 3, claims.size());
+    }
+
+    @org.junit.Test
+    public void testFilteredRealmAIdentityMapping() throws Exception {
+        
+        ClaimsManager claimsManager = new ClaimsManager();
+        
+        claimsManager.setIdentityMapper(new CustomIdentityMapper());
+        
+        RealmSupportClaimsHandler realmAHandler = new RealmSupportClaimsHandler();
+        realmAHandler.setRealm("A");
+        realmAHandler.setSupportedClaimTypes(Collections.singletonList(URI.create("Claim-A")));
+        
+        RealmSupportClaimsHandler realmBHandler = new RealmSupportClaimsHandler();
+        realmBHandler.setRealm("B");
+        realmBHandler.setSupportedClaimTypes(Collections.singletonList(URI.create("Claim-B")));
+        
+        RealmSupportClaimsHandler realmCHandler = new RealmSupportClaimsHandler();
+        realmCHandler.setRealm("A");
+        realmCHandler.setSupportedRealms(Collections.singletonList("A"));
+        realmCHandler.setSupportedClaimTypes(Collections.singletonList(URI.create("Claim-C")));
+        
+        List<ClaimsHandler> claimHandlers = new ArrayList<ClaimsHandler>();
+        claimHandlers.add(realmAHandler);
+        claimHandlers.add(realmBHandler);
+        claimHandlers.add(realmCHandler);
+        claimsManager.setClaimHandlers(Collections.unmodifiableList(claimHandlers));
+        
+        RequestClaimCollection requestedClaims = createRequestClaimCollection();
+        
+        ClaimsParameters parameters = new ClaimsParameters();
+        parameters.setRealm("A");
+        parameters.setPrincipal(new CustomTokenPrincipal("alice"));
+        ClaimCollection claims = claimsManager.retrieveClaimValues(requestedClaims, parameters);
+        Assert.assertEquals("Number of claims incorrect", 3, claims.size());
+        
+        //Asserts in RealmSupportClaimsHandler must succeed
+        
+    }
+    
+    
+    @org.junit.Test
+    public void testFilteredRealmBIdentityMapping() throws Exception {
+        
+        ClaimsManager claimsManager = new ClaimsManager();
+        
+        claimsManager.setIdentityMapper(new CustomIdentityMapper());
+        
+        RealmSupportClaimsHandler realmAHandler = new RealmSupportClaimsHandler();
+        realmAHandler.setRealm("A");
+        realmAHandler.setSupportedClaimTypes(Collections.singletonList(URI.create("Claim-A")));
+        
+        RealmSupportClaimsHandler realmBHandler = new RealmSupportClaimsHandler();
+        realmBHandler.setRealm("B");
+        realmBHandler.setSupportedClaimTypes(Collections.singletonList(URI.create("Claim-B")));
+        
+        RealmSupportClaimsHandler realmCHandler = new RealmSupportClaimsHandler();
+        realmCHandler.setRealm("A");
+        realmCHandler.setSupportedRealms(Collections.singletonList("A"));
+        realmCHandler.setSupportedClaimTypes(Collections.singletonList(URI.create("Claim-C")));
+        
+        List<ClaimsHandler> claimHandlers = new ArrayList<ClaimsHandler>();
+        claimHandlers.add(realmAHandler);
+        claimHandlers.add(realmBHandler);
+        claimHandlers.add(realmCHandler);
+        claimsManager.setClaimHandlers(Collections.unmodifiableList(claimHandlers));
+        
+        RequestClaimCollection requestedClaims = createRequestClaimCollection();
+        
+        ClaimsParameters parameters = new ClaimsParameters();
+        parameters.setRealm("B");
+        parameters.setPrincipal(new CustomTokenPrincipal("ALICE"));
+        ClaimCollection claims = claimsManager.retrieveClaimValues(requestedClaims, parameters);
+        Assert.assertEquals("Number of claims incorrect", 2, claims.size());
+        
+        //Asserts in RealmSupportClaimsHandler must succeed
+        
+    }
+    
+    private RequestClaimCollection createRequestClaimCollection() {
+        RequestClaimCollection requestedClaims = new RequestClaimCollection();
+        RequestClaim requestClaimA = new RequestClaim();
+        requestClaimA.setClaimType(URI.create("Claim-A"));
+        requestClaimA.setOptional(false);
+        requestedClaims.add(requestClaimA);
+        RequestClaim requestClaimB = new RequestClaim();
+        requestClaimB.setClaimType(URI.create("Claim-B"));
+        requestClaimB.setOptional(false);
+        requestedClaims.add(requestClaimB);
+        RequestClaim requestClaimC = new RequestClaim();
+        requestClaimC.setClaimType(URI.create("Claim-C"));
+        requestClaimC.setOptional(true);
+        requestedClaims.add(requestClaimC);
+        return requestedClaims;
+    }
+    
+}
+
+