/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved * * The contents of this file are subject to the terms * of the Common Development and Distribution License * (the License). You may not use this file except in * compliance with the License. * * You can obtain a copy of the License at * https://opensso.dev.java.net/public/CDDLv1.0.html or * opensso/legal/CDDLv1.0.txt * See the License for the specific language governing * permission and limitations under the License. * * When distributing Covered Code, include this CDDL * Header Notice in each file and include the License file * at opensso/legal/CDDLv1.0.txt. * If applicable, add the following below the CDDL Header, * with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * $Id: DefaultIDPAccountMapper.java,v 1.9 2008/11/10 22:57:02 veiming Exp $ * * Portions Copyrighted 2015 ForgeRock AS. */ package com.sun.identity.saml2.plugins; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import com.sun.identity.plugin.datastore.DataStoreProviderException; import com.sun.identity.plugin.session.SessionManager; import com.sun.identity.plugin.session.SessionProvider; import com.sun.identity.plugin.session.SessionException; import com.sun.identity.saml2.common.SAML2Exception; import com.sun.identity.saml2.common.SAML2Constants; import com.sun.identity.saml2.common.SAML2Utils; import com.sun.identity.saml2.assertion.NameID; import com.sun.identity.saml2.assertion.AssertionFactory; import com.sun.identity.saml2.profile.IDPCache; import com.sun.identity.saml2.profile.IDPSession; import com.sun.identity.saml2.profile.IDPSSOUtil; import com.sun.identity.saml2.profile.NameIDandSPpair; /** * This class DefaultIDPAccountMapper is the default implementation of the IDPAccountMapper * that is used to map the SAML protocol objects to the user accounts at the IdentityProvider * side of SAML v2 plugin. * Custom implementations may extend from this class to override some of these implementations if they choose to do so. */ public class DefaultIDPAccountMapper extends DefaultAccountMapper implements IDPAccountMapper { public DefaultIDPAccountMapper() { debug.message("DefaultIDPAccountMapper.constructor"); role = IDP; } @Override public NameID getNameID(Object session, String hostEntityID, String remoteEntityID, String realm, String nameIDFormat) throws SAML2Exception { String userID; try { SessionProvider sessionProv = SessionManager.getProvider(); userID = sessionProv.getPrincipalName(session); } catch (SessionException se) { throw new SAML2Exception(SAML2Utils.bundle.getString("invalidSSOToken")); } String nameIDValue = null; if (nameIDFormat.equals(SAML2Constants.NAMEID_TRANSIENT_FORMAT)) { String sessionIndex = IDPSSOUtil.getSessionIndex(session); if (sessionIndex != null) { IDPSession idpSession = IDPCache.idpSessionsByIndices.get(sessionIndex); if (idpSession != null) { List list = idpSession.getNameIDandSPpairs(); if (list != null) { for (NameIDandSPpair pair : list) { if (pair.getSPEntityID().equals(remoteEntityID)) { nameIDValue = pair.getNameID().getValue(); break; } } } } } if (nameIDValue == null) { nameIDValue = getNameIDValueFromUserProfile(realm, hostEntityID, userID, nameIDFormat); if (nameIDValue == null) { nameIDValue = SAML2Utils.createNameIdentifier(); } } } else { nameIDValue = getNameIDValueFromUserProfile(realm, hostEntityID, userID, nameIDFormat); if (nameIDValue == null) { if (nameIDFormat.equals(SAML2Constants.PERSISTENT)) { nameIDValue = SAML2Utils.createNameIdentifier(); } else { throw new SAML2Exception(bundle.getString("unableToGenerateNameIDValue")); } } } NameID nameID = AssertionFactory.getInstance().createNameID(); nameID.setValue(nameIDValue); nameID.setFormat(nameIDFormat); nameID.setNameQualifier(hostEntityID); nameID.setSPNameQualifier(remoteEntityID); nameID.setSPProvidedID(null); return nameID; } @Override public String getIdentity(NameID nameID, String hostEntityID, String remoteEntityID, String realm) throws SAML2Exception { if (nameID == null) { return null; } if (hostEntityID == null) { throw new SAML2Exception(bundle.getString("nullHostEntityID")); } if (remoteEntityID == null) { throw new SAML2Exception(bundle.getString("nullRemoteEntityID")); } if (realm == null) { throw new SAML2Exception(bundle.getString("nullRealm")); } if (debug.messageEnabled()) { debug.message("DefaultIDPAccountMapper.getIdentity: realm = " + realm + ", hostEntityID = " + hostEntityID + ", remoteEntityID = " + remoteEntityID); } try { return dsProvider.getUserID(realm, SAML2Utils.getNameIDKeyMap(nameID, hostEntityID, remoteEntityID, realm, role)); } catch (DataStoreProviderException dse) { debug.error("DefaultIDPAccountMapper.getIdentity(NameIDMappingRequest): ", dse); throw new SAML2Exception(dse.getMessage()); } } /** * {@inheritDoc} * * This implementation first checks whether NameID persistence has been completely disabled at the IdP level * (idpDisableNameIDPersistence setting), and if not, it will look at the SP configuration as well * (spDoNotWriteFederationInfo setting). * * @param realm {@inheritDoc} * @param hostEntityID {@inheritDoc} * @param remoteEntityID {@inheritDoc} * @param nameIDFormat {@inheritDoc} * @return {@inheritDoc} */ @Override public boolean shouldPersistNameIDFormat(String realm, String hostEntityID, String remoteEntityID, String nameIDFormat) { final boolean disableNameIDPersistence = Boolean.parseBoolean(SAML2Utils.getAttributeValueFromSSOConfig(realm, hostEntityID, SAML2Constants.IDP_ROLE, SAML2Constants.IDP_DISABLE_NAMEID_PERSISTENCE)); if (disableNameIDPersistence) { return false; } return !Boolean.parseBoolean(SAML2Utils.getAttributeValueFromSSOConfig(realm, remoteEntityID, SAML2Constants.SP_ROLE, SAML2Constants.SP_DO_NOT_WRITE_FEDERATION_INFO)); } protected String getNameIDValueFromUserProfile(String realm, String hostEntityID, String userID, String nameIDFormat) { String nameIDValue = null; Map formatAttrMap = getFormatAttributeMap(realm, hostEntityID); String attrName = formatAttrMap.get(nameIDFormat); if (attrName != null) { try { Set attrValues = dsProvider.getAttribute(userID, attrName); if (attrValues != null && !attrValues.isEmpty()) { nameIDValue = attrValues.iterator().next(); } } catch (DataStoreProviderException dspe) { if (debug.warningEnabled()) { debug.warning("DefaultIDPAccountMapper.getNameIDValueFromUserProfile:", dspe); } } } return nameIDValue; } private Map getFormatAttributeMap(String realm, String hostEntityID) { String key = hostEntityID + "|" + realm; Map formatAttributeMap = IDPCache.formatAttributeHash.get(key); if (formatAttributeMap != null) { return formatAttributeMap; } formatAttributeMap = new HashMap<>(); List values = SAML2Utils.getAllAttributeValueFromSSOConfig(realm, hostEntityID, role, SAML2Constants.NAME_ID_FORMAT_MAP); if (values != null) { for (String value : values) { int index = value.indexOf('='); if (index != -1) { String format = value.substring(0, index).trim(); String attrName = value.substring(index + 1).trim(); if (!format.isEmpty() && !attrName.isEmpty()) { formatAttributeMap.put(format, attrName); } } } } IDPCache.formatAttributeHash.put(key, formatAttributeMap); return formatAttributeMap; } }