/* * JOSSO: Java Open Single Sign-On * * Copyright 2004-2009, Atricore, Inc. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. * */ package org.josso.gateway.identity.service.store.virtual; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.josso.auth.Credential; import org.josso.auth.CredentialKey; import org.josso.auth.CredentialProvider; import org.josso.auth.CredentialStore; import org.josso.gateway.identity.exceptions.NoSuchUserException; import org.josso.gateway.identity.exceptions.SSOIdentityException; import org.josso.gateway.identity.service.BaseRole; import org.josso.gateway.identity.service.BaseUser; import org.josso.gateway.identity.service.store.AbstractStore; import org.josso.gateway.identity.service.store.UserKey; /** * @author <a href="mailto:gbrigand@josso.org">Gianluca Brigandi</a> * @version $Id: VirtualIdentityStore.java 1644 2010-07-27 19:31:39Z sgonzalez $ * @org.apache.xbean.XBean element="virtual-store" * <p/> * Virtual Identity Store which builds on multiple identity data sources for looking up user and entitlement * records. * It enables providing a unified view of one or more identity silos for consumption by Single Sign-On services. * It is useful in scenarios with multiple idenitity silos, potentially based on multiple technologies and information * models, for which an authoriative source for user information cannot be created or significant * effort is required. */ public class VirtualIdentityStore extends AbstractStore { private static final Log logger = LogFactory.getLog(VirtualIdentityStore.class); private List<IdentitySource> identitySources; private IdentityDataMappingPolicy identityDataMappingPolicy; public VirtualIdentityStore() { super(); } // Identity Store SPI implementation public BaseUser loadUser(UserKey key) throws NoSuchUserException, SSOIdentityException { BaseUser virtualUser = null; Collection<BaseUser> sourceUsers = new ArrayList<BaseUser>(); // Collect user information from the configured sources for (Iterator<IdentitySource> identitySourceIterator = identitySources.iterator(); identitySourceIterator.hasNext();) { IdentitySource identitySource = identitySourceIterator.next(); BaseUser sourceUser; try { sourceUser = identitySource.getBackingIdentityStore().loadUser(key); if (sourceUser != null) { sourceUsers.add(sourceUser); } } catch (NoSuchUserException e) { // do nothing ? } } if (sourceUsers.size() == 0) { throw new VirtualNoSuchUserException(key); } // Use the configured mapping policy to select user entries Collection<BaseUser> selectedUsers; selectedUsers = identityDataMappingPolicy.selectUser(Collections.unmodifiableCollection(sourceUsers)); if (selectedUsers != null && selectedUsers.size() > 0) { // Use the configured mapping policy to create a joint result from selected entries BaseUser jointEntry; jointEntry = identityDataMappingPolicy.joinUsers(selectedUsers); if (jointEntry == null) { throw new SSOIdentityException("Joining User Entries Failed"); } // Use the configured mapping policy to transformUser joint entry BaseUser transformedEntry; transformedEntry = identityDataMappingPolicy.transformUser(jointEntry); // Transformation is not mandatory if (transformedEntry == null) transformedEntry = jointEntry; // Use the configured mapping policy to assert the transformed joint entry identityDataMappingPolicy.validateUser(transformedEntry); virtualUser = transformedEntry; } return virtualUser; } public BaseRole[] findRolesByUserKey(UserKey key) throws SSOIdentityException { Collection<BaseRole> virtualUserRoles = new ArrayList<BaseRole>(); // Collect user information from the configured sources for (Iterator<IdentitySource> identitySourceIterator = identitySources.iterator(); identitySourceIterator.hasNext();) { IdentitySource identitySource = identitySourceIterator.next(); BaseRole[] baseRoles; baseRoles = identitySource.getBackingIdentityStore().findRolesByUserKey(key); if (baseRoles != null) { virtualUserRoles.addAll(Arrays.asList(baseRoles)); } } // Use the configured mapping policy to select role entries Collection<BaseRole> selectedRoles; selectedRoles = identityDataMappingPolicy.selectRoles(Collections.unmodifiableCollection(virtualUserRoles)); if (selectedRoles != null && selectedRoles.size() > 0) { // Use the configured mapping policy to create a joint result from selected entries Collection<BaseRole> jointRoles; jointRoles = identityDataMappingPolicy.joinRoles(selectedRoles); if (jointRoles == null) { throw new SSOIdentityException("Error Joining User Roles"); } // Use the configured mapping policy to transformUser joint entry Collection<BaseRole> transformedRoles; transformedRoles = identityDataMappingPolicy.transformRoles(jointRoles); // Transformation is not mandatory if (transformedRoles == null) transformedRoles = jointRoles; // Use the configured mapping policy to assert the transformed joint entry identityDataMappingPolicy.validateRoles(transformedRoles); virtualUserRoles = transformedRoles; } return virtualUserRoles.toArray(new BaseRole[0]); } public Credential[] loadCredentials(CredentialKey key, CredentialProvider cp) throws SSOIdentityException { Collection<Credential> virtualUserCredentials = new ArrayList<Credential>(); // Collect user information from the configured sources for (Iterator<IdentitySource> identitySourceIterator = identitySources.iterator(); identitySourceIterator.hasNext();) { IdentitySource identitySource = identitySourceIterator.next(); Credential[] Credentials; Credentials = ((CredentialStore) identitySource.getBackingIdentityStore()).loadCredentials(key, cp); if (Credentials != null) { virtualUserCredentials.addAll(Arrays.asList(Credentials)); } } // Use the configured mapping policy to select credential entries Collection<Credential> selectedCredentials; selectedCredentials = identityDataMappingPolicy.selectCredentials(Collections.unmodifiableCollection(virtualUserCredentials)); if (selectedCredentials != null && selectedCredentials.size() > 0) { // Use the configured mapping policy to create a joint result from selected entries Collection<Credential> jointCredentials; jointCredentials = identityDataMappingPolicy.joinCredentials(selectedCredentials); if (jointCredentials == null) { throw new SSOIdentityException("Error Joining User Credentials"); } // Use the configured mapping policy to transformUser joint entry Collection<Credential> transformedCredentials; transformedCredentials = identityDataMappingPolicy.transformCredentials(jointCredentials); // Transformation is not mandatory if (transformedCredentials == null) transformedCredentials = jointCredentials; // Use the configured mapping policy to assert the transformed joint entry identityDataMappingPolicy.validateCredentials(transformedCredentials); virtualUserCredentials = transformedCredentials; } return virtualUserCredentials.toArray(new Credential[0]); } public String loadUID(CredentialKey key, CredentialProvider cp) throws SSOIdentityException { String virtualUID = null; Collection<String> sourceUIDs = new ArrayList<String>(); // Collect UID information from the configured sources for (Iterator<IdentitySource> identitySourceIterator = identitySources.iterator(); identitySourceIterator.hasNext();) { IdentitySource identitySource = identitySourceIterator.next(); String sourceUID; sourceUID = ((CredentialStore) identitySource.getBackingIdentityStore()).loadUID(key, cp); if (sourceUID != null) { sourceUIDs.add(sourceUID); } } // Use the configured mapping policy to select UID entries Collection<String> selectedUIDs; selectedUIDs = identityDataMappingPolicy.selectUID(Collections.unmodifiableCollection(sourceUIDs)); if (selectedUIDs != null && selectedUIDs.size() > 0) { // Use the configured mapping policy to create a joint result from selected entries String jointEntry; jointEntry = identityDataMappingPolicy.joinUIDs(selectedUIDs); if (jointEntry == null) { throw new SSOIdentityException("Joining UID Entries Failed"); } // Use the configured mapping policy to transformUID joint entry String transformedEntry; transformedEntry = identityDataMappingPolicy.transformUID(jointEntry); // Transformation is not mandatory if (transformedEntry == null) transformedEntry = jointEntry; // Use the configured mapping policy to assert the transformed joint entry identityDataMappingPolicy.validateUID(transformedEntry); virtualUID = transformedEntry; } return virtualUID; } @Override public boolean userExists(UserKey key) throws SSOIdentityException { UserExistsOutcome virtualUserExistsOutcome = null; Collection<UserExistsOutcome> sourceUserExistsOutcomes = new ArrayList<UserExistsOutcome>(); // Collect user exists outcome information from the configured sources for (Iterator<IdentitySource> identitySourceIterator = getIdentitySources().iterator(); identitySourceIterator.hasNext();) { IdentitySource identitySource = identitySourceIterator.next(); boolean userExists = identitySource.getBackingIdentityStore().userExists(key); sourceUserExistsOutcomes.add(new UserExistsOutcome(userExists)); } // Use the configured mapping policy to select user exists outcomes Collection<UserExistsOutcome> selectedUserExistsOutcomes; selectedUserExistsOutcomes = getIdentityDataMappingPolicy().selectUserExistsOutcomes(Collections.unmodifiableCollection(sourceUserExistsOutcomes)); if (selectedUserExistsOutcomes != null && selectedUserExistsOutcomes.size() > 0) { // Use the configured mapping policy to create a joint result from selected entries UserExistsOutcome jointEntry; jointEntry = getIdentityDataMappingPolicy().joinUserExistsOutcomes(selectedUserExistsOutcomes); if (jointEntry == null) { throw new SSOIdentityException("Joining User Exists Outcomes Failed"); } // Use the configured mapping policy to transformUserExistsOutome joint entry UserExistsOutcome transformedEntry; transformedEntry = getIdentityDataMappingPolicy().transformUserExistsOutcome(jointEntry); // Transformation is not mandatory if (transformedEntry == null) transformedEntry = jointEntry; // Use the configured mapping policy to assert the transformed joint entry getIdentityDataMappingPolicy().validateUserExistsOutcome(transformedEntry); virtualUserExistsOutcome = transformedEntry; } if (virtualUserExistsOutcome == null) { throw new SSOIdentityException("Virtual User Exists Failed"); } return virtualUserExistsOutcome.isExists(); } /** * @return * @org.apache.xbean.Property alias="sources" * nestedType="org.josso.gateway.identity.service.store.virtual.IdentitySource" */ public List<IdentitySource> getIdentitySources() { return identitySources; } public void setIdentitySources(List<IdentitySource> identitySources) { this.identitySources = identitySources; } /** * @return * @org.apache.xbean.Property alias="mapping-policy" */ public IdentityDataMappingPolicy getIdentityDataMappingPolicy() { return identityDataMappingPolicy; } public void setIdentityDataMappingPolicy(IdentityDataMappingPolicy identityDataMappingPolicy) { this.identityDataMappingPolicy = identityDataMappingPolicy; } }