Search in sources :

Example 1 with NameIDInfo

use of com.sun.identity.saml2.common.NameIDInfo in project OpenAM by OpenRock.

the class SPACSUtils method processResponse.

/**
     * Authenticates user with <code>Response</code>.
     * Auth session upgrade will be called if input session is
     * not null.
     * Otherwise, saml2 auth module is called. The name of the auth module
     * is retrieved from <code>SPSSOConfig</code>. If not found, "SAML2" will
     * be used.
     *
     * @param request HTTP Servlet request
     * @param response HTTP Servlet response.
     * @param out the print writer for writing out presentation
     * @param metaAlias metaAlias for the service provider
     * @param session input session object. It could be null.
     * @param respInfo <code>ResponseInfo</code> to be verified.
     * @param realm realm or organization name of the service provider.
     * @param hostEntityId hosted service provider Entity ID.
     * @param metaManager <code>SAML2MetaManager</code> instance for meta operation.
     * @param auditor a <code>SAML2EventLogger</code> auditor object to hook into
     *                tracking information for the saml request
     * @return <code>Object</code> which holds result of the session.
     * @throws SAML2Exception if the processing failed.
     */
public static Object processResponse(HttpServletRequest request, HttpServletResponse response, PrintWriter out, String metaAlias, Object session, ResponseInfo respInfo, String realm, String hostEntityId, SAML2MetaManager metaManager, SAML2EventLogger auditor) throws SAML2Exception {
    String classMethod = "SPACSUtils.processResponse: ";
    if (SAML2Utils.debug.messageEnabled()) {
        SAML2Utils.debug.message(classMethod + "Response : " + respInfo.getResponse());
    }
    Map smap = null;
    try {
        // check Response/Assertion and get back a Map of relevant data
        smap = SAML2Utils.verifyResponse(request, response, respInfo.getResponse(), realm, hostEntityId, respInfo.getProfileBinding());
    } catch (SAML2Exception se) {
        // invoke SPAdapter for failure
        invokeSPAdapterForSSOFailure(hostEntityId, realm, request, response, smap, respInfo, SAML2ServiceProviderAdapter.INVALID_RESPONSE, se);
        throw se;
    }
    com.sun.identity.saml2.assertion.Subject assertionSubject = (com.sun.identity.saml2.assertion.Subject) smap.get(SAML2Constants.SUBJECT);
    NameID nameId = assertionSubject.getNameID();
    EncryptedID encId = assertionSubject.getEncryptedID();
    Assertion authnAssertion = (Assertion) smap.get(SAML2Constants.POST_ASSERTION);
    String sessionIndex = (String) smap.get(SAML2Constants.SESSION_INDEX);
    respInfo.setSessionIndex(sessionIndex);
    Integer authLevel = (Integer) smap.get(SAML2Constants.AUTH_LEVEL);
    Long maxSessionTime = (Long) smap.get(SAML2Constants.MAX_SESSION_TIME);
    String inRespToResp = (String) smap.get(SAML2Constants.IN_RESPONSE_TO);
    List assertions = (List) smap.get(SAML2Constants.ASSERTIONS);
    if (SAML2Utils.debug.messageEnabled()) {
        SAML2Utils.debug.message(classMethod + "Assertions : " + assertions);
    }
    SPSSOConfigElement spssoconfig = metaManager.getSPSSOConfig(realm, hostEntityId);
    // get mappers
    SPAccountMapper acctMapper = SAML2Utils.getSPAccountMapper(realm, hostEntityId);
    SPAttributeMapper attrMapper = SAML2Utils.getSPAttributeMapper(realm, hostEntityId);
    String assertionEncryptedAttr = SAML2Utils.getAttributeValueFromSPSSOConfig(spssoconfig, SAML2Constants.WANT_ASSERTION_ENCRYPTED);
    boolean needAttributeEncrypted = getNeedAttributeEncrypted(assertionEncryptedAttr, spssoconfig);
    boolean needNameIDEncrypted = getNeedNameIDEncrypted(assertionEncryptedAttr, spssoconfig);
    Set<PrivateKey> decryptionKeys = KeyUtil.getDecryptionKeys(spssoconfig);
    if (needNameIDEncrypted && encId == null) {
        SAML2Utils.debug.error(classMethod + "process: NameID was not encrypted.");
        SAML2Exception se = new SAML2Exception(SAML2Utils.bundle.getString("nameIDNotEncrypted"));
        // invoke SPAdapter for failure
        invokeSPAdapterForSSOFailure(hostEntityId, realm, request, response, smap, respInfo, SAML2ServiceProviderAdapter.INVALID_RESPONSE, se);
        throw se;
    }
    if (encId != null) {
        try {
            nameId = encId.decrypt(decryptionKeys);
        } catch (SAML2Exception se) {
            // invoke SPAdapter for failure
            invokeSPAdapterForSSOFailure(hostEntityId, realm, request, response, smap, respInfo, SAML2ServiceProviderAdapter.INVALID_RESPONSE, se);
            throw se;
        }
    }
    respInfo.setNameId(nameId);
    SPSSODescriptorElement spDesc = null;
    try {
        spDesc = metaManager.getSPSSODescriptor(realm, hostEntityId);
    } catch (SAML2MetaException ex) {
        SAML2Utils.debug.error(classMethod, ex);
    }
    if (spDesc == null) {
        SAML2Exception se = new SAML2Exception(SAML2Utils.bundle.getString("metaDataError"));
        invokeSPAdapterForSSOFailure(hostEntityId, realm, request, response, smap, respInfo, SAML2ServiceProviderAdapter.SSO_FAILED_META_DATA_ERROR, se);
        throw se;
    }
    String nameIDFormat = nameId.getFormat();
    if (nameIDFormat != null) {
        List spNameIDFormatList = spDesc.getNameIDFormat();
        if ((spNameIDFormatList != null) && (!spNameIDFormatList.isEmpty()) && (!spNameIDFormatList.contains(nameIDFormat))) {
            Object[] args = { nameIDFormat };
            SAML2Exception se = new SAML2Exception(SAML2Utils.BUNDLE_NAME, "unsupportedNameIDFormatSP", args);
            invokeSPAdapterForSSOFailure(hostEntityId, realm, request, response, smap, respInfo, SAML2ServiceProviderAdapter.INVALID_RESPONSE, se);
            throw se;
        }
    }
    boolean isTransient = SAML2Constants.NAMEID_TRANSIENT_FORMAT.equals(nameIDFormat);
    boolean isPersistent = SAML2Constants.PERSISTENT.equals(nameIDFormat);
    boolean ignoreProfile = SAML2PluginsUtils.isIgnoredProfile(realm);
    String existUserName = null;
    SessionProvider sessionProvider = null;
    try {
        sessionProvider = SessionManager.getProvider();
    } catch (SessionException se) {
        // invoke SPAdapter for failure
        SAML2Exception se2 = new SAML2Exception(se);
        invokeSPAdapterForSSOFailure(hostEntityId, realm, request, response, smap, respInfo, SAML2ServiceProviderAdapter.SSO_FAILED_SESSION_ERROR, se2);
        throw se2;
    }
    if (session != null) {
        try {
            existUserName = sessionProvider.getPrincipalName(session);
        } catch (SessionException se) {
            // invoke SPAdapter for failure
            SAML2Exception se2 = new SAML2Exception(se);
            invokeSPAdapterForSSOFailure(hostEntityId, realm, request, response, smap, respInfo, SAML2ServiceProviderAdapter.SSO_FAILED_SESSION_ERROR, se2);
            throw se2;
        }
    }
    String remoteHostId = authnAssertion.getIssuer().getValue();
    String userName = null;
    boolean isNewAccountLink = false;
    boolean shouldPersistNameID = isPersistent || (!isTransient && !ignoreProfile && acctMapper.shouldPersistNameIDFormat(realm, hostEntityId, remoteHostId, nameIDFormat));
    try {
        if (shouldPersistNameID) {
            if (SAML2Utils.debug.messageEnabled()) {
                SAML2Utils.debug.message(classMethod + "querying data store for existing federation links: realm = " + realm + " hostEntityID = " + hostEntityId + " remoteEntityID = " + remoteHostId);
            }
            try {
                userName = SAML2Utils.getDataStoreProvider().getUserID(realm, SAML2Utils.getNameIDKeyMap(nameId, hostEntityId, remoteHostId, realm, SAML2Constants.SP_ROLE));
            } catch (DataStoreProviderException dse) {
                SAML2Utils.debug.error(classMethod + "DataStoreProviderException whilst retrieving NameID " + "information", dse);
                throw new SAML2Exception(dse.getMessage());
            }
        }
        if (userName == null) {
            userName = acctMapper.getIdentity(authnAssertion, hostEntityId, realm);
            isNewAccountLink = true;
        }
    } catch (SAML2Exception se) {
        // invoke SPAdapter for failure
        invokeSPAdapterForSSOFailure(hostEntityId, realm, request, response, smap, respInfo, SAML2ServiceProviderAdapter.SSO_FAILED_NO_USER_MAPPING, se);
        throw se;
    }
    if (userName == null && respInfo.isLocalLogin()) {
        // In case we just got authenticated locally, we should accept the freshly authenticated session's principal
        // as the username corresponding to the received assertion.
        userName = existUserName;
    }
    if (null != auditor) {
        auditor.setUserId(userName);
    }
    if (SAML2Utils.debug.messageEnabled()) {
        SAML2Utils.debug.message(classMethod + "process: userName =[" + userName + "]");
    }
    List attrs = null;
    for (Iterator it = assertions.iterator(); it.hasNext(); ) {
        Assertion assertion = (Assertion) it.next();
        List origAttrs = getSAMLAttributes(assertion, needAttributeEncrypted, decryptionKeys);
        if (origAttrs != null && !origAttrs.isEmpty()) {
            if (attrs == null) {
                attrs = new ArrayList();
            }
            attrs.addAll(origAttrs);
        }
    }
    Map attrMap = null;
    if (attrs != null) {
        try {
            attrMap = attrMapper.getAttributes(attrs, userName, hostEntityId, remoteHostId, realm);
        } catch (SAML2Exception se) {
            // invoke SPAdapter for failure
            invokeSPAdapterForSSOFailure(hostEntityId, realm, request, response, smap, respInfo, SAML2ServiceProviderAdapter.SSO_FAILED_ATTRIBUTE_MAPPING, se);
            throw se;
        }
    }
    if (SAML2Utils.debug.messageEnabled()) {
        SAML2Utils.debug.message(classMethod + "process: remoteHostId = " + remoteHostId);
        SAML2Utils.debug.message(classMethod + "process: attrMap = " + attrMap);
    }
    respInfo.setAttributeMap(attrMap);
    // return error code for local user login
    if (StringUtils.isEmpty(userName)) {
        // map the user to the existing session.
        if (session != null) {
            try {
                sessionProvider.invalidateSession(session, request, response);
            } catch (SessionException se) {
                SAML2Utils.debug.error("An error occurred while trying to invalidate session", se);
            }
        }
        throw new SAML2Exception(SAML2Utils.bundle.getString("noUserMapping"));
    }
    boolean writeFedInfo = isNewAccountLink && shouldPersistNameID;
    if (SAML2Utils.debug.messageEnabled()) {
        SAML2Utils.debug.message(classMethod + "userName : " + userName);
        SAML2Utils.debug.message(classMethod + "writeFedInfo : " + writeFedInfo);
    }
    AuthnRequest authnRequest = null;
    if (smap != null) {
        authnRequest = (AuthnRequest) smap.get(SAML2Constants.AUTHN_REQUEST);
    }
    if (inRespToResp != null && inRespToResp.length() != 0) {
        SPCache.requestHash.remove(inRespToResp);
    }
    Map sessionInfoMap = new HashMap();
    sessionInfoMap.put(SessionProvider.REALM, realm);
    sessionInfoMap.put(SessionProvider.PRINCIPAL_NAME, userName);
    // set client info. always use client IP address to prevent
    // reverse host lookup
    String clientAddr = ClientUtils.getClientIPAddress(request);
    sessionInfoMap.put(SessionProvider.HOST, clientAddr);
    sessionInfoMap.put(SessionProvider.HOST_NAME, clientAddr);
    sessionInfoMap.put(SessionProvider.AUTH_LEVEL, String.valueOf(authLevel));
    request.setAttribute(SessionProvider.ATTR_MAP, attrMap);
    try {
        session = sessionProvider.createSession(sessionInfoMap, request, response, null);
    } catch (SessionException se) {
        // invoke SPAdapter for failure
        int failureCode = SAML2ServiceProviderAdapter.SSO_FAILED_SESSION_GENERATION;
        int sessCode = se.getErrCode();
        if (sessCode == SessionException.AUTH_USER_INACTIVE) {
            failureCode = SAML2ServiceProviderAdapter.SSO_FAILED_AUTH_USER_INACTIVE;
        } else if (sessCode == SessionException.AUTH_USER_LOCKED) {
            failureCode = SAML2ServiceProviderAdapter.SSO_FAILED_AUTH_USER_LOCKED;
        } else if (sessCode == SessionException.AUTH_ACCOUNT_EXPIRED) {
            failureCode = SAML2ServiceProviderAdapter.SSO_FAILED_AUTH_ACCOUNT_EXPIRED;
        }
        if (SAML2Utils.debug.messageEnabled()) {
            SAML2Utils.debug.message("SPACSUtils.processResponse : error code=" + sessCode, se);
        }
        SAML2Exception se2 = new SAML2Exception(se);
        invokeSPAdapterForSSOFailure(hostEntityId, realm, request, response, smap, respInfo, failureCode, se2);
        throw se2;
    }
    // set metaAlias
    String[] values = { metaAlias };
    try {
        setAttrMapInSession(sessionProvider, attrMap, session);
        setDiscoBootstrapCredsInSSOToken(sessionProvider, authnAssertion, session);
        sessionProvider.setProperty(session, SAML2Constants.SP_METAALIAS, values);
    } catch (SessionException se) {
        // invoke SPAdapter for failure
        SAML2Exception se2 = new SAML2Exception(se);
        invokeSPAdapterForSSOFailure(hostEntityId, realm, request, response, smap, respInfo, SAML2ServiceProviderAdapter.SSO_FAILED_SESSION_ERROR, se2);
        throw se2;
    }
    NameIDInfo info = null;
    String affiID = nameId.getSPNameQualifier();
    boolean isDualRole = SAML2Utils.isDualRole(hostEntityId, realm);
    AffiliationDescriptorType affiDesc = null;
    if (affiID != null && !affiID.isEmpty()) {
        affiDesc = metaManager.getAffiliationDescriptor(realm, affiID);
    }
    if (affiDesc != null) {
        if (!affiDesc.getAffiliateMember().contains(hostEntityId)) {
            throw new SAML2Exception(SAML2Utils.bundle.getString("spNotAffiliationMember"));
        }
        if (isDualRole) {
            info = new NameIDInfo(affiID, remoteHostId, nameId, SAML2Constants.DUAL_ROLE, true);
        } else {
            info = new NameIDInfo(affiID, remoteHostId, nameId, SAML2Constants.SP_ROLE, true);
        }
    } else {
        if (isDualRole) {
            info = new NameIDInfo(hostEntityId, remoteHostId, nameId, SAML2Constants.DUAL_ROLE, false);
        } else {
            info = new NameIDInfo(hostEntityId, remoteHostId, nameId, SAML2Constants.SP_ROLE, false);
        }
    }
    Map props = new HashMap();
    String nameIDValueString = info.getNameIDValue();
    props.put(LogUtil.NAME_ID, info.getNameIDValue());
    try {
        userName = sessionProvider.getPrincipalName(session);
    } catch (SessionException se) {
        // invoke SPAdapter for failure
        SAML2Exception se2 = new SAML2Exception(se);
        invokeSPAdapterForSSOFailure(hostEntityId, realm, request, response, smap, respInfo, SAML2ServiceProviderAdapter.SSO_FAILED_SESSION_ERROR, se2);
        throw se2;
    }
    String[] data1 = { userName, nameIDValueString };
    LogUtil.access(Level.INFO, LogUtil.SUCCESS_FED_SSO, data1, session, props);
    // write fed info into data store
    if (writeFedInfo) {
        try {
            AccountUtils.setAccountFederation(info, userName);
        } catch (SAML2Exception se) {
            // invoke SPAdapter for failure
            invokeSPAdapterForSSOFailure(hostEntityId, realm, request, response, smap, respInfo, SAML2ServiceProviderAdapter.FEDERATION_FAILED_WRITING_ACCOUNT_INFO, se);
            throw se;
        }
        String[] data = { userName, "" };
        if (LogUtil.isAccessLoggable(Level.FINE)) {
            data[1] = info.toValueString();
        }
        LogUtil.access(Level.INFO, LogUtil.FED_INFO_WRITTEN, data, session, props);
    }
    String requestID = respInfo.getResponse().getInResponseTo();
    // save info in memory for logout
    saveInfoInMemory(sessionProvider, session, sessionIndex, metaAlias, info, IDPProxyUtil.isIDPProxyEnabled(requestID), isTransient);
    // invoke SP Adapter
    SAML2ServiceProviderAdapter spAdapter = SAML2Utils.getSPAdapterClass(hostEntityId, realm);
    if (spAdapter != null) {
        boolean redirected = spAdapter.postSingleSignOnSuccess(hostEntityId, realm, request, response, out, session, authnRequest, respInfo.getResponse(), respInfo.getProfileBinding(), writeFedInfo);
        String[] value = null;
        if (redirected) {
            value = new String[] { "true" };
        } else {
            value = new String[] { "false" };
        }
        try {
            sessionProvider.setProperty(session, SAML2Constants.RESPONSE_REDIRECTED, value);
        } catch (SessionException ex) {
            SAML2Utils.debug.warning("SPSingleLogout.processResp", ex);
        } catch (UnsupportedOperationException ex) {
            SAML2Utils.debug.warning("SPSingleLogout.processResp", ex);
        }
    }
    String assertionID = authnAssertion.getID();
    if (respInfo.getProfileBinding().equals(SAML2Constants.HTTP_POST)) {
        SPCache.assertionByIDCache.put(assertionID, SAML2Constants.ONETIME);
        try {
            if (SAML2FailoverUtils.isSAML2FailoverEnabled()) {
                SAML2FailoverUtils.saveSAML2TokenWithoutSecondaryKey(assertionID, SAML2Constants.ONETIME, ((Long) smap.get(SAML2Constants.NOTONORAFTER)).longValue() / 1000);
            }
        } catch (SAML2TokenRepositoryException se) {
            SAML2Utils.debug.error(classMethod + "There was a problem saving the assertionID to the SAML2 Token Repository for assertionID:" + assertionID, se);
        }
    }
    respInfo.setAssertion(authnAssertion);
    return session;
}
Also used : PrivateKey(java.security.PrivateKey) HashMap(java.util.HashMap) SPSSODescriptorElement(com.sun.identity.saml2.jaxb.metadata.SPSSODescriptorElement) ArrayList(java.util.ArrayList) SessionException(com.sun.identity.plugin.session.SessionException) EncryptedID(com.sun.identity.saml2.assertion.EncryptedID) SPAccountMapper(com.sun.identity.saml2.plugins.SPAccountMapper) Iterator(java.util.Iterator) List(java.util.List) ArrayList(java.util.ArrayList) SAML2ServiceProviderAdapter(com.sun.identity.saml2.plugins.SAML2ServiceProviderAdapter) SAML2MetaException(com.sun.identity.saml2.meta.SAML2MetaException) SessionProvider(com.sun.identity.plugin.session.SessionProvider) DataStoreProviderException(com.sun.identity.plugin.datastore.DataStoreProviderException) NameIDInfo(com.sun.identity.saml2.common.NameIDInfo) NameID(com.sun.identity.saml2.assertion.NameID) Assertion(com.sun.identity.saml2.assertion.Assertion) SPSSOConfigElement(com.sun.identity.saml2.jaxb.entityconfig.SPSSOConfigElement) AffiliationDescriptorType(com.sun.identity.saml2.jaxb.metadata.AffiliationDescriptorType) Subject(com.sun.identity.saml2.assertion.Subject) Subject(com.sun.identity.saml2.assertion.Subject) SAML2Exception(com.sun.identity.saml2.common.SAML2Exception) AuthnRequest(com.sun.identity.saml2.protocol.AuthnRequest) SPAttributeMapper(com.sun.identity.saml2.plugins.SPAttributeMapper) SAML2TokenRepositoryException(org.forgerock.openam.federation.saml2.SAML2TokenRepositoryException) Map(java.util.Map) HashMap(java.util.HashMap)

Example 2 with NameIDInfo

use of com.sun.identity.saml2.common.NameIDInfo in project OpenAM by OpenRock.

the class SPACSUtils method saveInfoInMemory.

public static void saveInfoInMemory(SessionProvider sessionProvider, Object session, String sessionIndex, String metaAlias, NameIDInfo info, boolean isIDPProxy, boolean isTransient) throws SAML2Exception {
    String infoKeyString = (new NameIDInfoKey(info.getNameIDValue(), info.getHostEntityID(), info.getRemoteEntityID())).toValueString();
    String infoKeyAttribute = AccountUtils.getNameIDInfoKeyAttribute();
    String[] fromToken = null;
    try {
        fromToken = sessionProvider.getProperty(session, infoKeyAttribute);
        if (fromToken == null || fromToken.length == 0 || fromToken[0] == null || fromToken[0].length() == 0) {
            String[] values = { infoKeyString };
            sessionProvider.setProperty(session, infoKeyAttribute, values);
        } else {
            if (fromToken[0].indexOf(infoKeyString) == -1) {
                String[] values = { fromToken[0] + SAML2Constants.SECOND_DELIM + infoKeyString };
                sessionProvider.setProperty(session, infoKeyAttribute, values);
            }
        }
        if (isTransient) {
            String nameIDInfoStr = info.toValueString();
            String infoAttribute = AccountUtils.getNameIDInfoAttribute();
            String[] nameIDInfoStrs = sessionProvider.getProperty(session, infoAttribute);
            if (nameIDInfoStrs == null) {
                nameIDInfoStrs = new String[1];
                nameIDInfoStrs[0] = nameIDInfoStr;
            } else {
                Set nameIDInfoStrSet = new HashSet();
                for (int i = 0; i < nameIDInfoStrs.length; i++) {
                    nameIDInfoStrSet.add(nameIDInfoStrs[i]);
                }
                nameIDInfoStrSet.add(nameIDInfoStr);
                nameIDInfoStrs = (String[]) nameIDInfoStrSet.toArray(new String[nameIDInfoStrSet.size()]);
            }
            sessionProvider.setProperty(session, infoAttribute, nameIDInfoStrs);
        }
    } catch (SessionException sessE) {
        throw new SAML2Exception(sessE);
    }
    String tokenID = sessionProvider.getSessionID(session);
    if (!SPCache.isFedlet) {
        List fedSessions = (List) SPCache.fedSessionListsByNameIDInfoKey.get(infoKeyString);
        if (fedSessions == null) {
            synchronized (SPCache.fedSessionListsByNameIDInfoKey) {
                fedSessions = (List) SPCache.fedSessionListsByNameIDInfoKey.get(infoKeyString);
                if (fedSessions == null) {
                    fedSessions = new ArrayList();
                }
            }
            synchronized (fedSessions) {
                fedSessions.add(new SPFedSession(sessionIndex, tokenID, info, metaAlias));
                SPCache.fedSessionListsByNameIDInfoKey.put(infoKeyString, fedSessions);
            }
            if ((agent != null) && agent.isRunning() && (saml2Svc != null)) {
                saml2Svc.setFedSessionCount((long) SPCache.fedSessionListsByNameIDInfoKey.size());
            }
            if (isIDPProxy) {
                //IDP Proxy 
                IDPSession idpSess = (IDPSession) IDPCache.idpSessionsBySessionID.get(tokenID);
                if (idpSess == null) {
                    idpSess = new IDPSession(session);
                    IDPCache.idpSessionsBySessionID.put(tokenID, idpSess);
                }
                if (SAML2Utils.debug.messageEnabled()) {
                    SAML2Utils.debug.message("Add Session Partner: " + info.getRemoteEntityID());
                }
                idpSess.addSessionPartner(new SAML2SessionPartner(info.getRemoteEntityID(), true));
            // end of IDP Proxy        
            }
        } else {
            synchronized (fedSessions) {
                Iterator iter = fedSessions.iterator();
                boolean found = false;
                while (iter.hasNext()) {
                    SPFedSession temp = (SPFedSession) iter.next();
                    String idpSessionIndex = null;
                    if (temp != null) {
                        idpSessionIndex = temp.idpSessionIndex;
                    }
                    if ((idpSessionIndex != null) && (idpSessionIndex.equals(sessionIndex))) {
                        temp.spTokenID = tokenID;
                        temp.info = info;
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    fedSessions.add(new SPFedSession(sessionIndex, tokenID, info, metaAlias));
                    SPCache.fedSessionListsByNameIDInfoKey.put(infoKeyString, fedSessions);
                    if ((agent != null) && agent.isRunning() && (saml2Svc != null)) {
                        saml2Svc.setFedSessionCount((long) SPCache.fedSessionListsByNameIDInfoKey.size());
                    }
                }
            }
        }
        SPCache.fedSessionListsByNameIDInfoKey.put(infoKeyString, fedSessions);
        if ((agent != null) && agent.isRunning() && (saml2Svc != null)) {
            saml2Svc.setFedSessionCount((long) SPCache.fedSessionListsByNameIDInfoKey.size());
        }
    }
    try {
        sessionProvider.addListener(session, new SPSessionListener(infoKeyString, tokenID));
    } catch (SessionException e) {
        SAML2Utils.debug.error("SPACSUtils.saveInfoInMemory: " + "Unable to add session listener.");
    }
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) ArrayList(java.util.ArrayList) SessionException(com.sun.identity.plugin.session.SessionException) SAML2Exception(com.sun.identity.saml2.common.SAML2Exception) Iterator(java.util.Iterator) List(java.util.List) ArrayList(java.util.ArrayList) NameIDInfoKey(com.sun.identity.saml2.common.NameIDInfoKey) HashSet(java.util.HashSet)

Example 3 with NameIDInfo

use of com.sun.identity.saml2.common.NameIDInfo in project OpenAM by OpenRock.

the class IDPSSOUtil method getSubject.

/**
     * Returns a <code>SAML Subject</code> object
     *
     * @param session           the user's session
     * @param authnReq          the <code>AuthnRequest</code> object
     * @param acsURL            the <code>ACS</code> service <code>url</code>
     * @param nameIDFormat      the <code>NameIDFormat</code>
     * @param realm             The realm name
     * @param idpEntityID       the entity id of the identity provider
     * @param recipientEntityID the entity id of the response recipient
     * @param effectiveTime     the effective time of the assertion
     * @param affiliationID     affiliationID for IDP initiated SSO
     * @return the <code>SAML Subject</code> object
     * @throws SAML2Exception if the operation is not successful
     */
private static Subject getSubject(Object session, AuthnRequest authnReq, String acsURL, String nameIDFormat, String realm, String idpEntityID, String recipientEntityID, int effectiveTime, String affiliationID) throws SAML2Exception {
    String classMethod = "IDPSSOUtil.getSubject: ";
    Subject subject = AssertionFactory.getInstance().createSubject();
    boolean ignoreProfile = false;
    String userName = null;
    try {
        userName = sessionProvider.getPrincipalName(session);
        ignoreProfile = SAML2Utils.isIgnoreProfileSet(session);
    } catch (SessionException se) {
        SAML2Utils.debug.error(classMethod + "There was a problem with the session.", se);
        throw new SAML2Exception(SAML2Utils.bundle.getString("invalidSSOToken"));
    }
    // allow create is the default
    boolean allowCreate = true;
    String remoteEntityID = null;
    String spNameQualifier = null;
    boolean isAffiliation = false;
    if (authnReq != null) {
        remoteEntityID = authnReq.getIssuer().getValue();
        NameIDPolicy nameIDPolicy = authnReq.getNameIDPolicy();
        if (nameIDPolicy != null) {
            // this will take care of affiliation
            allowCreate = nameIDPolicy.isAllowCreate();
            spNameQualifier = nameIDPolicy.getSPNameQualifier();
            if (spNameQualifier != null && !spNameQualifier.isEmpty()) {
                AffiliationDescriptorType affiDesc = metaManager.getAffiliationDescriptor(realm, spNameQualifier);
                if (affiDesc != null) {
                    if (affiDesc.getAffiliateMember().contains(remoteEntityID)) {
                        isAffiliation = true;
                        remoteEntityID = spNameQualifier;
                    } else {
                        throw new SAML2Exception(SAML2Utils.bundle.getString("spNotAffiliationMember"));
                    }
                }
            } else {
                spNameQualifier = recipientEntityID;
            }
        }
    } else {
        // IDP initialted SSO
        if (affiliationID != null) {
            AffiliationDescriptorType affiDesc = metaManager.getAffiliationDescriptor(realm, affiliationID);
            if (affiDesc == null) {
                throw new SAML2Exception(SAML2Utils.bundle.getString("affiliationNotFound"));
            }
            if (affiDesc.getAffiliateMember().contains(recipientEntityID)) {
                isAffiliation = true;
                remoteEntityID = affiliationID;
                spNameQualifier = affiliationID;
            } else {
                throw new SAML2Exception(SAML2Utils.bundle.getString("spNotAffiliationMember"));
            }
        } else {
            remoteEntityID = recipientEntityID;
            spNameQualifier = recipientEntityID;
        }
    }
    SPSSODescriptorElement spsso = getSPSSODescriptor(realm, recipientEntityID, classMethod);
    if (spsso == null) {
        String[] data = { recipientEntityID };
        LogUtil.error(Level.INFO, LogUtil.SP_METADATA_ERROR, data, null);
        throw new SAML2Exception(SAML2Utils.bundle.getString("metaDataError"));
    }
    IDPSSODescriptorElement idpsso = metaManager.getIDPSSODescriptor(realm, idpEntityID);
    if (idpsso == null) {
        String[] data = { idpEntityID };
        LogUtil.error(Level.INFO, LogUtil.IDP_METADATA_ERROR, data, null);
        throw new SAML2Exception(SAML2Utils.bundle.getString("metaDataError"));
    }
    nameIDFormat = SAML2Utils.verifyNameIDFormat(nameIDFormat, spsso, idpsso);
    boolean isTransient = SAML2Constants.NAMEID_TRANSIENT_FORMAT.equals(nameIDFormat);
    boolean isPersistent = SAML2Constants.PERSISTENT.equals(nameIDFormat);
    NameIDInfo nameIDInfo;
    NameID nameID = null;
    IDPAccountMapper idpAccountMapper = SAML2Utils.getIDPAccountMapper(realm, idpEntityID);
    //Use-cases for NameID persistence:
    //* persistent NameID -> The NameID MUST be stored
    //* transient NameID -> The NameID MUST NOT be stored
    //* ignored user profile mode -> The NameID CANNOT be stored
    //* for any other cases -> The NameID MAY be stored based on customizable logic
    boolean shouldPersistNameID = isPersistent || (!isTransient && !ignoreProfile && idpAccountMapper.shouldPersistNameIDFormat(realm, idpEntityID, remoteEntityID, nameIDFormat));
    if (!isTransient) {
        String userID;
        try {
            userID = sessionProvider.getPrincipalName(session);
        } catch (SessionException se) {
            SAML2Utils.debug.error(classMethod + "Unable to get principal name from the session.", se);
            throw new SAML2Exception(SAML2Utils.bundle.getString("invalidSSOToken"));
        }
        if (isPersistent || shouldPersistNameID) {
            nameIDInfo = AccountUtils.getAccountFederation(userID, idpEntityID, remoteEntityID);
            if (nameIDInfo != null) {
                nameID = nameIDInfo.getNameID();
                if (!nameIDFormat.equals(nameID.getFormat())) {
                    AccountUtils.removeAccountFederation(nameIDInfo, userID);
                    DoManageNameID.removeIDPFedSession(remoteEntityID, nameID.getValue());
                    nameID = null;
                }
            }
        }
    }
    if (nameID == null) {
        if (!allowCreate && isPersistent) {
            throw new SAML2InvalidNameIDPolicyException(SAML2Utils.bundle.getString("cannotCreateNameID"));
        }
        nameID = idpAccountMapper.getNameID(session, idpEntityID, spNameQualifier, realm, nameIDFormat);
        SAML2Utils.debug.message(classMethod + " shouldPersistNameID = " + shouldPersistNameID);
        if (shouldPersistNameID && allowCreate) {
            // write federation info into the persistent datastore
            if (SAML2Utils.isDualRole(idpEntityID, realm)) {
                nameIDInfo = new NameIDInfo(idpEntityID, remoteEntityID, nameID, SAML2Constants.DUAL_ROLE, false);
            } else {
                nameIDInfo = new NameIDInfo(idpEntityID, remoteEntityID, nameID, SAML2Constants.IDP_ROLE, isAffiliation);
            }
            AccountUtils.setAccountFederation(nameIDInfo, userName);
        }
    }
    subject.setNameID(nameID);
    if (isTransient) {
        IDPCache.userIDByTransientNameIDValue.put(nameID.getValue(), userName);
    }
    String inResponseTo = null;
    if (authnReq != null) {
        inResponseTo = authnReq.getID();
    }
    SubjectConfirmation sc = getSubjectConfirmation(inResponseTo, acsURL, effectiveTime);
    if (sc == null) {
        SAML2Utils.debug.error(classMethod + "Unable to get subject confirmation");
        throw new SAML2Exception(SAML2Utils.bundle.getString("noSubjectConfirmation"));
    }
    List list = new ArrayList();
    list.add(sc);
    subject.setSubjectConfirmation(list);
    return subject;
}
Also used : NameIDInfo(com.sun.identity.saml2.common.NameIDInfo) IDPAccountMapper(com.sun.identity.saml2.plugins.IDPAccountMapper) NameIDPolicy(com.sun.identity.saml2.protocol.NameIDPolicy) NameID(com.sun.identity.saml2.assertion.NameID) SPSSODescriptorElement(com.sun.identity.saml2.jaxb.metadata.SPSSODescriptorElement) ArrayList(java.util.ArrayList) SessionException(com.sun.identity.plugin.session.SessionException) AffiliationDescriptorType(com.sun.identity.saml2.jaxb.metadata.AffiliationDescriptorType) Subject(com.sun.identity.saml2.assertion.Subject) SAML2Exception(com.sun.identity.saml2.common.SAML2Exception) SubjectConfirmation(com.sun.identity.saml2.assertion.SubjectConfirmation) List(java.util.List) ArrayList(java.util.ArrayList) SAML2InvalidNameIDPolicyException(com.sun.identity.saml2.common.SAML2InvalidNameIDPolicyException) IDPSSODescriptorElement(com.sun.identity.saml2.jaxb.metadata.IDPSSODescriptorElement)

Example 4 with NameIDInfo

use of com.sun.identity.saml2.common.NameIDInfo in project OpenAM by OpenRock.

the class DoManageNameID method processManageNameIDRequest.

private static Status processManageNameIDRequest(ManageNameIDRequest mniRequest, String realm, String hostEntityID, String remoteEntityID, String hostRole, String userID) throws Exception {
    String method = "processManageNameIDRequest: ";
    if (debug.messageEnabled()) {
        debug.message(method + "Host EntityID is : " + hostEntityID);
        debug.message(method + "Host role is : " + hostRole);
        debug.message(method + "Realm  is : " + realm);
    }
    NameID nameID = getNameIDFromMNIRequest(mniRequest, realm, hostEntityID, hostRole);
    NameIDInfo oldNameIDInfo = getNameIDInfo(userID, hostEntityID, remoteEntityID, hostRole, realm, nameID.getSPNameQualifier(), true);
    NameID oldNameID = null;
    if (oldNameIDInfo != null) {
        oldNameID = oldNameIDInfo.getNameID();
    }
    if (oldNameID == null) {
        // log manage name id failure
        logError("unknownPrinciapl", LogUtil.UNKNOWN_PRINCIPAL, mniRequest.toXMLString(true, true));
        return SAML2Utils.generateStatus(SAML2Constants.REQUESTER, SAML2Constants.UNKNOWN_PRINCIPAL, null);
    }
    List spFedSessions = null;
    IDPSession idpSession = null;
    // Terminate
    if (hostRole.equalsIgnoreCase(SAML2Constants.IDP_ROLE)) {
        idpSession = removeIDPFedSession(remoteEntityID, oldNameID.getValue());
    } else {
        spFedSessions = (List) SPCache.fedSessionListsByNameIDInfoKey.remove(oldNameIDInfo.getNameIDInfoKey().toValueString());
        if ((agent != null) && agent.isRunning() && (saml2Svc != null)) {
            saml2Svc.setFedSessionCount((long) SPCache.fedSessionListsByNameIDInfoKey.size());
        }
    }
    if (!AccountUtils.removeAccountFederation(oldNameIDInfo, userID)) {
        // log termination failure
        logError("unableToTerminate", LogUtil.UNABLE_TO_TERMINATE, userID);
        return SAML2Utils.generateStatus(SAML2Constants.RESPONDER, SAML2Utils.bundle.getString("unableToTerminate"));
    }
    if (mniRequest.getTerminate()) {
        // log termination success
        logAccess("requestSuccess", LogUtil.SUCCESS_FED_TERMINATION, userID);
        return SAML2Utils.generateStatus(SAML2Constants.SUCCESS, SAML2Utils.bundle.getString("requestSuccess"));
    }
    // newID case
    NewID newID = getNewIDFromMNIRequest(mniRequest, realm, hostEntityID, hostRole);
    boolean isAffiliation = oldNameIDInfo.isAffiliation();
    String spNameQualifier = oldNameID.getSPNameQualifier();
    if (hostRole.equalsIgnoreCase(SAML2Constants.IDP_ROLE)) {
        NameID newNameID = AssertionFactory.getInstance().createNameID();
        newNameID.setValue(oldNameID.getValue());
        newNameID.setNameQualifier(oldNameID.getNameQualifier());
        newNameID.setSPNameQualifier(spNameQualifier);
        newNameID.setFormat(oldNameID.getFormat());
        newNameID.setSPProvidedID(newID.getValue());
        NameIDInfo newNameIDinfo = new NameIDInfo(hostEntityID, (isAffiliation ? spNameQualifier : remoteEntityID), newNameID, SAML2Constants.IDP_ROLE, isAffiliation);
        AccountUtils.setAccountFederation(newNameIDinfo, userID);
        if (idpSession != null) {
            // there are active session using this Name id
            NameIDandSPpair pair = new NameIDandSPpair(newNameID, remoteEntityID);
            synchronized (IDPCache.idpSessionsByIndices) {
                List list = (List) idpSession.getNameIDandSPpairs();
                list.add(pair);
            }
        }
        // log new name id success
        logAccess("requestSuccess", LogUtil.SUCCESS_NEW_NAMEID, userID);
        return SAML2Utils.generateStatus(SAML2Constants.SUCCESS, SAML2Utils.bundle.getString("requestSuccess"));
    }
    // SP ROLE
    NameID newNameID = AssertionFactory.getInstance().createNameID();
    newNameID.setValue(newID.getValue());
    newNameID.setNameQualifier(oldNameID.getNameQualifier());
    newNameID.setSPProvidedID(oldNameID.getSPProvidedID());
    newNameID.setSPNameQualifier(spNameQualifier);
    newNameID.setFormat(oldNameID.getFormat());
    NameIDInfo newNameIDInfo = new NameIDInfo((isAffiliation ? spNameQualifier : hostEntityID), remoteEntityID, newNameID, hostRole, isAffiliation);
    AccountUtils.setAccountFederation(newNameIDInfo, userID);
    if (spFedSessions != null) {
        String newInfoKeyStr = newNameIDInfo.getNameIDInfoKey().toValueString();
        String infoKeyAttribute = AccountUtils.getNameIDInfoKeyAttribute();
        synchronized (spFedSessions) {
            for (Iterator iter = spFedSessions.iterator(); iter.hasNext(); ) {
                SPFedSession spFedSession = (SPFedSession) iter.next();
                spFedSession.info = newNameIDInfo;
                String tokenID = spFedSession.spTokenID;
                try {
                    Object session = sessionProvider.getSession(tokenID);
                    String[] fromToken = sessionProvider.getProperty(session, infoKeyAttribute);
                    if ((fromToken == null) || (fromToken.length == 0) || (fromToken[0] == null) || (fromToken[0].length() == 0)) {
                        String[] values = { newInfoKeyStr };
                        sessionProvider.setProperty(session, infoKeyAttribute, values);
                    } else {
                        if (fromToken[0].indexOf(newInfoKeyStr) == -1) {
                            String[] values = { fromToken[0] + SAML2Constants.SECOND_DELIM + newInfoKeyStr };
                            sessionProvider.setProperty(session, infoKeyAttribute, values);
                        }
                    }
                } catch (SessionException ex) {
                    debug.error("DoManageNameID." + "processManageNameIDRequest:", ex);
                }
            }
        }
        SPCache.fedSessionListsByNameIDInfoKey.put(newInfoKeyStr, spFedSessions);
        if ((agent != null) && agent.isRunning() && (saml2Svc != null)) {
            saml2Svc.setFedSessionCount((long) SPCache.fedSessionListsByNameIDInfoKey.size());
        }
    }
    // log new name id success
    logAccess("requestSuccess", LogUtil.SUCCESS_NEW_NAMEID, userID);
    return SAML2Utils.generateStatus(SAML2Constants.SUCCESS, SAML2Utils.bundle.getString("requestSuccess"));
}
Also used : NewID(com.sun.identity.saml2.protocol.NewID) NameIDInfo(com.sun.identity.saml2.common.NameIDInfo) NameID(com.sun.identity.saml2.assertion.NameID) SessionException(com.sun.identity.plugin.session.SessionException) Iterator(java.util.Iterator) List(java.util.List)

Example 5 with NameIDInfo

use of com.sun.identity.saml2.common.NameIDInfo in project OpenAM by OpenRock.

the class AccountUtils method getAccountFederation.

/**
     * Returns the account federation information of a user for the given 
     * identity provider and a service provider. 
     * @param userID user id for which account federation needs to be returned.
     * @param hostEntityID <code>EntityID</code> of the hosted entity.
     * @param remoteEntityID <code>EntityID</code> of the remote entity.
     * @return the account federation info object.
     *         null if the account federation does not exist.
     * @exception WSFederationException if account federation retrieval failed.
     */
public static NameIDInfo getAccountFederation(String userID, String hostEntityID, String remoteEntityID) throws WSFederationException {
    String classMethod = "AccountUtils.getAccountFederation: ";
    if (debug.messageEnabled()) {
        debug.message(classMethod);
    }
    if (userID == null) {
        throw new WSFederationException(WSFederationUtils.bundle.getString("nullUserID"));
    }
    if (hostEntityID == null) {
        throw new WSFederationException(WSFederationUtils.bundle.getString("nullHostEntityID"));
    }
    if (remoteEntityID == null) {
        throw new WSFederationException(WSFederationUtils.bundle.getString("nullRemoteEntityID"));
    }
    try {
        Set set = WSFederationUtils.dsProvider.getAttribute(userID, getNameIDInfoAttribute());
        if (set == null || set.isEmpty()) {
            if (WSFederationUtils.debug.messageEnabled()) {
                WSFederationUtils.debug.message(classMethod + "user does not have any account federations.");
            }
            return null;
        }
        String filter = hostEntityID + DELIM + remoteEntityID + DELIM;
        if (WSFederationUtils.debug.messageEnabled()) {
            WSFederationUtils.debug.message(classMethod + " filter = " + filter + " userID = " + userID);
        }
        String info = null;
        for (Iterator iter = set.iterator(); iter.hasNext(); ) {
            String value = (String) iter.next();
            if (value.startsWith(filter)) {
                info = value;
                break;
            }
        }
        if (info == null) {
            if (WSFederationUtils.debug.messageEnabled()) {
                WSFederationUtils.debug.message(classMethod + "user does not have account federation " + " corresponding to =" + filter);
            }
            return null;
        }
        return NameIDInfo.parse(info);
    } catch (DataStoreProviderException dse) {
        WSFederationUtils.debug.error(classMethod + "Info: DataStoreProviderException", dse);
        throw new WSFederationException(dse);
    } catch (SAML2Exception se) {
        WSFederationUtils.debug.error(classMethod + "Info: SAML2Exception", se);
        throw new WSFederationException(se);
    }
}
Also used : SAML2Exception(com.sun.identity.saml2.common.SAML2Exception) DataStoreProviderException(com.sun.identity.plugin.datastore.DataStoreProviderException) HashSet(java.util.HashSet) Set(java.util.Set) Iterator(java.util.Iterator)

Aggregations

SAML2Exception (com.sun.identity.saml2.common.SAML2Exception)15 NameIDInfo (com.sun.identity.saml2.common.NameIDInfo)13 NameID (com.sun.identity.saml2.assertion.NameID)11 SessionException (com.sun.identity.plugin.session.SessionException)6 HashSet (java.util.HashSet)6 Set (java.util.Set)6 HashMap (java.util.HashMap)5 Iterator (java.util.Iterator)5 List (java.util.List)5 Map (java.util.Map)5 DataStoreProviderException (com.sun.identity.plugin.datastore.DataStoreProviderException)4 NameIDInfoKey (com.sun.identity.saml2.common.NameIDInfoKey)4 SSOException (com.iplanet.sso.SSOException)3 AffiliationDescriptorType (com.sun.identity.saml2.jaxb.metadata.AffiliationDescriptorType)3 NameIDPolicy (com.sun.identity.saml2.protocol.NameIDPolicy)3 ArrayList (java.util.ArrayList)3 SAML2TokenRepositoryException (org.forgerock.openam.federation.saml2.SAML2TokenRepositoryException)3 CLIException (com.sun.identity.cli.CLIException)2 IOutput (com.sun.identity.cli.IOutput)2 AMIdentity (com.sun.identity.idm.AMIdentity)2