package org.atricore.idbus.capabilities.sso.support.federation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.atricore.idbus.capabilities.sso.support.profiles.DCEPACAttributeDefinition; import org.atricore.idbus.kernel.main.federation.IdentityMapper; import org.atricore.idbus.kernel.main.federation.SubjectAttribute; import org.atricore.idbus.kernel.main.federation.SubjectNameID; import org.atricore.idbus.kernel.main.federation.SubjectRole; import javax.security.auth.Subject; import java.security.Principal; import java.util.HashSet; import java.util.Set; /** * The mapped subject contains local and remote subject information * * @author <a href="mailto:sgonzalez@atricore.org">Sebastian Gonzalez Oyuela</a> * @version $Id$ */ public class MergedSubjectIdentityMapper implements IdentityMapper { private static final Log logger = LogFactory.getLog(MergedSubjectIdentityMapper.class); private boolean useLocalId = true; private Set<String> roleAttributeNames = new HashSet<String>(); public MergedSubjectIdentityMapper() { roleAttributeNames.add(DCEPACAttributeDefinition.GROUPS.getValue()); roleAttributeNames.add(DCEPACAttributeDefinition.GROUP.getValue()); } public Set<String> getRoleAttributeNames() { return roleAttributeNames; } public void setRoleAttributeNames(Set<String> roleAttributeNames) { this.roleAttributeNames = roleAttributeNames; } public boolean isUseLocalId() { return useLocalId; } public void setUseLocalId(boolean useLocalId) { this.useLocalId = useLocalId; } public Subject map(Subject remoteSubject, Subject localSubject) { return map(remoteSubject, localSubject, null); } public Subject map(Subject remoteSubject, Subject localSubject, Set<Principal> additionalPrincipals) { Subject federatedSubject = null; Set<Principal> merged = new HashSet<Principal>(); if (useLocalId) { Set<SubjectNameID> subjectNameID = localSubject.getPrincipals(SubjectNameID.class); // federated subject is identified using local account name identifier for (SubjectNameID sc : subjectNameID) { merged.add(sc); } } else { Set<SubjectNameID> subjectNameID = remoteSubject.getPrincipals(SubjectNameID.class); // federated subject is identified using local account name identifier for (SubjectNameID sc : subjectNameID) { merged.add(sc); } } for (Principal p : remoteSubject.getPrincipals()) { if (p instanceof SubjectNameID) continue; if (logger.isTraceEnabled()) logger.trace("Merging IDP principal " + p); // If Subject attribute is configured as role name attribute, also add a SubjectRole if (p instanceof SubjectAttribute) { SubjectAttribute sa = (SubjectAttribute) p; if (roleAttributeNames.contains(sa.getName())) { merged.add(new SubjectRole(sa.getValue())); } } merged.add(p); } for (Principal p : localSubject.getPrincipals()) { if (p instanceof SubjectNameID) continue; if (logger.isTraceEnabled()) logger.trace("Merging Local principal " + p); if (!merged.contains (p)) merged.add(p); } if (additionalPrincipals != null) { for (Principal p : additionalPrincipals) { if (p instanceof SubjectNameID) continue; if (logger.isTraceEnabled()) logger.trace("Merging Additional principal " + p); // If Subject attribute is configured as role name attribute, also add a SubjectRole if (p instanceof SubjectAttribute) { SubjectAttribute sa = (SubjectAttribute) p; if (roleAttributeNames.contains(sa.getName())) { SubjectRole r = new SubjectRole(sa.getValue()); if (!merged.contains(r)) merged.add(r); } } if (!merged.contains(p)) merged.add(p); } } /* // federated subject entitlements are the ones conveyed in the idp subject with // an extra tag for (SubjectAttribute sa : idpSubject.getPrincipals(SubjectAttribute.class)) { // Map SAML 2.0 Groups as roles if (sa.getName().equals("urn:oasis:names:tc:SAML:2.0:profiles:attribute:DCE:groups")) { merged.add(new SubjectRole(sa.getValue())); } } */ federatedSubject = new Subject(true, merged, localSubject.getPublicCredentials(), localSubject.getPrivateCredentials()); if (logger.isTraceEnabled()) logger.trace("Merged subject " + federatedSubject); return federatedSubject; } }