Search in sources :

Example 1 with SAML2ServiceProviderAdapter

use of com.sun.identity.saml2.plugins.SAML2ServiceProviderAdapter 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 SAML2ServiceProviderAdapter

use of com.sun.identity.saml2.plugins.SAML2ServiceProviderAdapter in project OpenAM by OpenRock.

the class SPSSOFederate method initiateECPRequest.

/**
     * Parses the request parameters and builds ECP Request to sent to the IDP.
     *
     * @param request the HttpServletRequest.
     * @param response the HttpServletResponse.
     *
     * @throws SAML2Exception if error creating AuthnRequest.
     * @throws IOException if error sending AuthnRequest to ECP.
     */
public static void initiateECPRequest(HttpServletRequest request, HttpServletResponse response) throws SAML2Exception, IOException {
    if (!isFromECP(request)) {
        SAML2Utils.debug.error("SPSSOFederate.initiateECPRequest: " + "invalid HTTP request from ECP.");
        SAMLUtils.sendError(request, response, HttpServletResponse.SC_BAD_REQUEST, "invalidHttpRequestFromECP", SAML2Utils.bundle.getString("invalidHttpRequestFromECP"));
        return;
    }
    String metaAlias = request.getParameter("metaAlias");
    Map paramsMap = SAML2Utils.getParamsMap(request);
    // get the sp entity ID from the metaAlias
    String spEntityID = sm.getEntityByMetaAlias(metaAlias);
    String realm = getRealm(SAML2MetaUtils.getRealmByMetaAlias(metaAlias));
    if (SAML2Utils.debug.messageEnabled()) {
        SAML2Utils.debug.message("SPSSOFederate.initiateECPRequest: " + "spEntityID is " + spEntityID + ", realm is " + realm);
    }
    try {
        // Retreive MetaData 
        if (sm == null) {
            throw new SAML2Exception(SAML2Utils.bundle.getString("errorMetaManager"));
        }
        SPSSOConfigElement spEntityCfg = sm.getSPSSOConfig(realm, spEntityID);
        Map spConfigAttrsMap = null;
        if (spEntityCfg != null) {
            spConfigAttrsMap = SAML2MetaUtils.getAttributes(spEntityCfg);
        }
        // get SPSSODescriptor
        SPSSODescriptorElement spsso = sm.getSPSSODescriptor(realm, spEntityID);
        if (spsso == null) {
            String[] data = { spEntityID };
            LogUtil.error(Level.INFO, LogUtil.SP_METADATA_ERROR, data, null);
            throw new SAML2Exception(SAML2Utils.bundle.getString("metaDataError"));
        }
        String[] data = { spEntityID, realm };
        LogUtil.access(Level.INFO, LogUtil.RECEIVED_HTTP_REQUEST_ECP, data, null);
        List extensionsList = getExtensionsList(spEntityID, realm);
        // create AuthnRequest 
        AuthnRequest authnRequest = createAuthnRequest(realm, spEntityID, paramsMap, spConfigAttrsMap, extensionsList, spsso, null, null, true);
        // invoke SP Adapter class if registered
        SAML2ServiceProviderAdapter spAdapter = SAML2Utils.getSPAdapterClass(spEntityID, realm);
        if (spAdapter != null) {
            spAdapter.preSingleSignOnRequest(spEntityID, realm, null, request, response, authnRequest);
        }
        String alias = SAML2Utils.getSigningCertAlias(realm, spEntityID, SAML2Constants.SP_ROLE);
        PrivateKey signingKey = KeyUtil.getKeyProviderInstance().getPrivateKey(alias);
        if (signingKey != null) {
            authnRequest.sign(signingKey, null);
        } else {
            SAML2Utils.debug.error("SPSSOFederate.initiateECPRequest: " + "Unable to find signing key.");
            throw new SAML2Exception(SAML2Utils.bundle.getString("metaDataError"));
        }
        ECPFactory ecpFactory = ECPFactory.getInstance();
        // Default URL if relayState not present? in providerConfig?
        // TODO get Default URL from metadata 
        String relayState = getParameter(paramsMap, SAML2Constants.RELAY_STATE);
        String ecpRelayStateXmlStr = "";
        if (relayState != null && relayState.length() > 0) {
            String relayStateID = getRelayStateID(relayState, authnRequest.getID());
            ECPRelayState ecpRelayState = ecpFactory.createECPRelayState();
            ecpRelayState.setValue(relayStateID);
            ecpRelayState.setMustUnderstand(Boolean.TRUE);
            ecpRelayState.setActor(SAML2Constants.SOAP_ACTOR_NEXT);
            ecpRelayStateXmlStr = ecpRelayState.toXMLString(true, true);
        }
        ECPRequest ecpRequest = ecpFactory.createECPRequest();
        ecpRequest.setIssuer(createIssuer(spEntityID));
        ecpRequest.setMustUnderstand(Boolean.TRUE);
        ecpRequest.setActor(SAML2Constants.SOAP_ACTOR_NEXT);
        ecpRequest.setIsPassive(authnRequest.isPassive());
        SAML2IDPFinder ecpIDPFinder = SAML2Utils.getECPIDPFinder(realm, spEntityID);
        if (ecpIDPFinder != null) {
            List idps = ecpIDPFinder.getPreferredIDP(authnRequest, spEntityID, realm, request, response);
            if ((idps != null) && (!idps.isEmpty())) {
                SAML2MetaManager saml2MetaManager = SAML2Utils.getSAML2MetaManager();
                List idpEntries = null;
                for (Iterator iter = idps.iterator(); iter.hasNext(); ) {
                    String idpEntityID = (String) iter.next();
                    IDPSSODescriptorElement idpDesc = saml2MetaManager.getIDPSSODescriptor(realm, idpEntityID);
                    if (idpDesc != null) {
                        IDPEntry idpEntry = ProtocolFactory.getInstance().createIDPEntry();
                        idpEntry.setProviderID(idpEntityID);
                        String description = SAML2Utils.getAttributeValueFromSSOConfig(realm, idpEntityID, SAML2Constants.IDP_ROLE, SAML2Constants.ENTITY_DESCRIPTION);
                        idpEntry.setName(description);
                        List ssoServiceList = idpDesc.getSingleSignOnService();
                        String ssoURL = getSSOURL(ssoServiceList, SAML2Constants.SOAP);
                        idpEntry.setLoc(ssoURL);
                        if (idpEntries == null) {
                            idpEntries = new ArrayList();
                        }
                        idpEntries.add(idpEntry);
                    }
                }
                if (idpEntries != null) {
                    IDPList idpList = ProtocolFactory.getInstance().createIDPList();
                    idpList.setIDPEntries(idpEntries);
                    ecpRequest.setIDPList(idpList);
                    Map attrs = SAML2MetaUtils.getAttributes(spEntityCfg);
                    List values = (List) attrs.get(SAML2Constants.ECP_REQUEST_IDP_LIST_GET_COMPLETE);
                    if ((values != null) && (!values.isEmpty())) {
                        GetComplete getComplete = ProtocolFactory.getInstance().createGetComplete();
                        getComplete.setValue((String) values.get(0));
                        idpList.setGetComplete(getComplete);
                    }
                }
            }
        }
        String paosRequestXmlStr = "";
        try {
            PAOSRequest paosRequest = new PAOSRequest(authnRequest.getAssertionConsumerServiceURL(), SAML2Constants.PAOS_ECP_SERVICE, null, Boolean.TRUE, SAML2Constants.SOAP_ACTOR_NEXT);
            paosRequestXmlStr = paosRequest.toXMLString(true, true);
        } catch (PAOSException paosex) {
            SAML2Utils.debug.error("SPSSOFederate.initiateECPRequest:", paosex);
            throw new SAML2Exception(paosex.getMessage());
        }
        String header = paosRequestXmlStr + ecpRequest.toXMLString(true, true) + ecpRelayStateXmlStr;
        String body = authnRequest.toXMLString(true, true);
        try {
            SOAPMessage reply = SOAPCommunicator.getInstance().createSOAPMessage(header, body, false);
            String[] data2 = { spEntityID, realm, "" };
            if (LogUtil.isAccessLoggable(Level.FINE)) {
                data2[2] = SOAPCommunicator.getInstance().soapMessageToString(reply);
            }
            LogUtil.access(Level.INFO, LogUtil.SEND_ECP_PAOS_REQUEST, data2, null);
            // are generated as part of the save.
            if (reply.saveRequired()) {
                reply.saveChanges();
            }
            response.setStatus(HttpServletResponse.SC_OK);
            SAML2Utils.putHeaders(reply.getMimeHeaders(), response);
            response.setContentType(PAOSConstants.PAOS_MIME_TYPE);
            // Write out the message on the response stream
            OutputStream os = response.getOutputStream();
            reply.writeTo(os);
            os.flush();
        } catch (SOAPException soapex) {
            SAML2Utils.debug.error("SPSSOFederate.initiateECPRequest", soapex);
            String[] data3 = { spEntityID, realm };
            LogUtil.error(Level.INFO, LogUtil.SEND_ECP_PAOS_REQUEST_FAILED, data3, null);
            SAMLUtils.sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "soapError", soapex.getMessage());
            return;
        }
        AuthnRequestInfo reqInfo = new AuthnRequestInfo(request, response, realm, spEntityID, null, authnRequest, relayState, paramsMap);
        synchronized (SPCache.requestHash) {
            SPCache.requestHash.put(authnRequest.getID(), reqInfo);
        }
        if (SAML2FailoverUtils.isSAML2FailoverEnabled()) {
            // sessionExpireTime is counted in seconds
            long sessionExpireTime = System.currentTimeMillis() / 1000 + SPCache.interval;
            String key = authnRequest.getID();
            try {
                SAML2FailoverUtils.saveSAML2TokenWithoutSecondaryKey(key, new AuthnRequestInfoCopy(reqInfo), sessionExpireTime);
                if (SAML2Utils.debug.messageEnabled()) {
                    SAML2Utils.debug.message("SPSSOFederate.initiateECPRequest:" + " SAVE AuthnRequestInfoCopy for requestID " + key);
                }
            } catch (SAML2TokenRepositoryException e) {
                SAML2Utils.debug.error("SPSSOFederate.initiateECPRequest: There was a problem saving the " + "AuthnRequestInfoCopy in the SAML2 Token Repository for requestID " + key, e);
            }
        }
    } catch (SAML2MetaException sme) {
        SAML2Utils.debug.error("SPSSOFederate:Error retrieving metadata", sme);
        throw new SAML2Exception(SAML2Utils.bundle.getString("metaDataError"));
    }
}
Also used : PrivateKey(java.security.PrivateKey) SPSSODescriptorElement(com.sun.identity.saml2.jaxb.metadata.SPSSODescriptorElement) GetComplete(com.sun.identity.saml2.protocol.GetComplete) OutputStream(java.io.OutputStream) ArrayList(java.util.ArrayList) PAOSException(com.sun.identity.liberty.ws.paos.PAOSException) SOAPMessage(javax.xml.soap.SOAPMessage) ECPFactory(com.sun.identity.saml2.ecp.ECPFactory) SOAPException(javax.xml.soap.SOAPException) ECPRelayState(com.sun.identity.saml2.ecp.ECPRelayState) Iterator(java.util.Iterator) List(java.util.List) IDPList(com.sun.identity.saml2.protocol.IDPList) ArrayList(java.util.ArrayList) SAML2ServiceProviderAdapter(com.sun.identity.saml2.plugins.SAML2ServiceProviderAdapter) SAML2IDPFinder(com.sun.identity.saml2.plugins.SAML2IDPFinder) SAML2MetaException(com.sun.identity.saml2.meta.SAML2MetaException) ECPRequest(com.sun.identity.saml2.ecp.ECPRequest) SPSSOConfigElement(com.sun.identity.saml2.jaxb.entityconfig.SPSSOConfigElement) IDPList(com.sun.identity.saml2.protocol.IDPList) SAML2MetaManager(com.sun.identity.saml2.meta.SAML2MetaManager) SAML2Exception(com.sun.identity.saml2.common.SAML2Exception) AuthnRequest(com.sun.identity.saml2.protocol.AuthnRequest) SAML2TokenRepositoryException(org.forgerock.openam.federation.saml2.SAML2TokenRepositoryException) IDPEntry(com.sun.identity.saml2.protocol.IDPEntry) Map(java.util.Map) PAOSRequest(com.sun.identity.liberty.ws.paos.PAOSRequest) IDPSSODescriptorElement(com.sun.identity.saml2.jaxb.metadata.IDPSSODescriptorElement)

Example 3 with SAML2ServiceProviderAdapter

use of com.sun.identity.saml2.plugins.SAML2ServiceProviderAdapter in project OpenAM by OpenRock.

the class IDPProxyUtil method sendProxyAuthnRequest.

/**
     * Sends a new AuthnRequest to the authenticating provider. 
     * @param authnRequest original AuthnRequest sent by the service provider.
     * @param preferredIDP IDP to be proxied. 
     * @param spSSODescriptor SPSSO Descriptor Element
     * @param hostedEntityId hosted provider ID 
     * @param request HttpServletRequest 
     * @param response HttpServletResponse
     * @param realm Realm
     * @param relayState the Relay State 
     * @param originalBinding The binding used to send the original AuthnRequest.
     * @exception SAML2Exception for any SAML2 failure.
     * @exception IOException if there is a failure in redirection.
     */
public static void sendProxyAuthnRequest(AuthnRequest authnRequest, String preferredIDP, SPSSODescriptorElement spSSODescriptor, String hostedEntityId, HttpServletRequest request, HttpServletResponse response, String realm, String relayState, String originalBinding) throws SAML2Exception, IOException {
    String classMethod = "IDPProxyUtil.sendProxyAuthnRequest: ";
    String destination = null;
    SPSSODescriptorElement localDescriptor = null;
    SPSSOConfigElement localDescriptorConfig = null;
    IDPSSODescriptorElement idpDescriptor = null;
    String binding;
    try {
        idpDescriptor = IDPSSOUtil.metaManager.getIDPSSODescriptor(realm, preferredIDP);
        List<SingleSignOnServiceElement> ssoServiceList = idpDescriptor.getSingleSignOnService();
        SingleSignOnServiceElement endpoint = getMatchingSSOEndpoint(ssoServiceList, originalBinding);
        if (endpoint == null) {
            SAML2Utils.debug.error(classMethod + "Single Sign-on service is not found for the proxying IDP.");
            throw new SAML2Exception(SAML2Utils.bundle.getString("ssoServiceNotFoundIDPProxy"));
        }
        binding = endpoint.getBinding();
        destination = endpoint.getLocation();
        localDescriptor = IDPSSOUtil.metaManager.getSPSSODescriptor(realm, hostedEntityId);
        localDescriptorConfig = IDPSSOUtil.metaManager.getSPSSOConfig(realm, hostedEntityId);
    } catch (SAML2MetaException e) {
        SAML2Utils.debug.error(classMethod, e);
        throw new SAML2Exception(e.getMessage());
    }
    AuthnRequest newAuthnRequest = getNewAuthnRequest(hostedEntityId, destination, realm, authnRequest);
    // invoke SP Adapter class if registered
    SAML2ServiceProviderAdapter spAdapter = SAML2Utils.getSPAdapterClass(hostedEntityId, realm);
    if (spAdapter != null) {
        spAdapter.preSingleSignOnRequest(hostedEntityId, preferredIDP, realm, request, response, newAuthnRequest);
    }
    if (SAML2Utils.debug.messageEnabled()) {
        SAML2Utils.debug.message(classMethod + "New Authentication request:" + newAuthnRequest.toXMLString());
    }
    String requestID = newAuthnRequest.getID();
    // save the AuthnRequest in the IDPCache so that it can be
    // retrieved later when the user successfully authenticates
    IDPCache.authnRequestCache.put(requestID, newAuthnRequest);
    // save the original AuthnRequest
    IDPCache.proxySPAuthnReqCache.put(requestID, authnRequest);
    boolean signingNeeded = idpDescriptor.isWantAuthnRequestsSigned() || localDescriptor.isAuthnRequestsSigned();
    // check if relayState is present and get the unique
    // id which will be appended to the SSO URL before
    // redirecting
    String relayStateID = null;
    if (relayState != null && relayState.length() > 0) {
        relayStateID = SPSSOFederate.getRelayStateID(relayState, authnRequest.getID());
    }
    if (binding.equals(SAML2Constants.HTTP_POST)) {
        if (signingNeeded) {
            String certAlias = SPSSOFederate.getParameter(SAML2MetaUtils.getAttributes(localDescriptorConfig), SAML2Constants.SIGNING_CERT_ALIAS);
            SPSSOFederate.signAuthnRequest(certAlias, newAuthnRequest);
        }
        String authXMLString = newAuthnRequest.toXMLString(true, true);
        String encodedReqMsg = SAML2Utils.encodeForPOST(authXMLString);
        SAML2Utils.postToTarget(request, response, "SAMLRequest", encodedReqMsg, "RelayState", relayStateID, destination);
    } else {
        String authReqXMLString = newAuthnRequest.toXMLString(true, true);
        if (SAML2Utils.debug.messageEnabled()) {
            SAML2Utils.debug.message(classMethod + " AuthnRequest: " + authReqXMLString);
        }
        String encodedXML = SAML2Utils.encodeForRedirect(authReqXMLString);
        StringBuffer queryString = new StringBuffer().append(SAML2Constants.SAML_REQUEST).append(SAML2Constants.EQUAL).append(encodedXML);
        //TODO:  should it be newAuthnRequest??? 
        if (relayStateID != null && relayStateID.length() > 0) {
            queryString.append("&").append(SAML2Constants.RELAY_STATE).append("=").append(URLEncDec.encode(relayStateID));
        }
        StringBuffer redirectURL = new StringBuffer().append(destination).append(destination.contains("?") ? "&" : "?");
        if (signingNeeded) {
            String certAlias = SPSSOFederate.getParameter(SAML2MetaUtils.getAttributes(localDescriptorConfig), SAML2Constants.SIGNING_CERT_ALIAS);
            String signedQueryStr = SPSSOFederate.signQueryString(queryString.toString(), certAlias);
            redirectURL.append(signedQueryStr);
        } else {
            redirectURL.append(queryString);
        }
        response.sendRedirect(redirectURL.toString());
    }
    String[] data = { destination };
    LogUtil.access(Level.INFO, LogUtil.REDIRECT_TO_SP, data, null);
    AuthnRequestInfo reqInfo = new AuthnRequestInfo(request, response, realm, hostedEntityId, preferredIDP, newAuthnRequest, relayState, null);
    synchronized (SPCache.requestHash) {
        SPCache.requestHash.put(requestID, reqInfo);
    }
    if (SAML2FailoverUtils.isSAML2FailoverEnabled()) {
        try {
            // sessionExpireTime is counted in seconds
            long sessionExpireTime = System.currentTimeMillis() / 1000 + SPCache.interval;
            SAML2FailoverUtils.saveSAML2TokenWithoutSecondaryKey(requestID, new AuthnRequestInfoCopy(reqInfo), sessionExpireTime);
            if (SAML2Utils.debug.messageEnabled()) {
                SAML2Utils.debug.message(classMethod + " SAVE AuthnRequestInfoCopy for requestID " + requestID);
            }
        } catch (SAML2TokenRepositoryException se) {
            SAML2Utils.debug.error(classMethod + " SAVE AuthnRequestInfoCopy for requestID " + requestID + ", failed!", se);
        }
    }
}
Also used : SPSSODescriptorElement(com.sun.identity.saml2.jaxb.metadata.SPSSODescriptorElement) SPSSOConfigElement(com.sun.identity.saml2.jaxb.entityconfig.SPSSOConfigElement) SingleSignOnServiceElement(com.sun.identity.saml2.jaxb.metadata.SingleSignOnServiceElement) SAML2Exception(com.sun.identity.saml2.common.SAML2Exception) AuthnRequest(com.sun.identity.saml2.protocol.AuthnRequest) SAML2TokenRepositoryException(org.forgerock.openam.federation.saml2.SAML2TokenRepositoryException) SAML2ServiceProviderAdapter(com.sun.identity.saml2.plugins.SAML2ServiceProviderAdapter) SAML2MetaException(com.sun.identity.saml2.meta.SAML2MetaException) IDPSSODescriptorElement(com.sun.identity.saml2.jaxb.metadata.IDPSSODescriptorElement)

Example 4 with SAML2ServiceProviderAdapter

use of com.sun.identity.saml2.plugins.SAML2ServiceProviderAdapter in project OpenAM by OpenRock.

the class SAML2Utils method verifyResponse.

/**
     * Verifies single sign on <code>Response</code> and returns information
     * to SAML2 auth module for further processing. This method is used by
     * SAML2 auth module only.
     *
     * @param httpRequest    HttpServletRequest
     * @param httpResponse   HttpServletResponse
     * @param response       Single Sign On <code>Response</code>.
     * @param orgName        name of the realm or organization the provider is in.
     * @param hostEntityId   Entity ID of the hosted provider.
     * @param profileBinding Profile binding used.
     * @return A Map of information extracted from the Response. The keys of
     * map are:
     * <code>SAML2Constants.SUBJECT</code>,
     * <code>SAML2Constants.POST_ASSERTION</code>,
     * <code>SAML2Constants.ASSERTIONS</code>,
     * <code>SAML2Constants.SESSION_INDEX</code>,
     * <code>SAML2Constants.AUTH_LEVEL</code>,
     * <code>SAML2Constants.MAX_SESSION_TIME</code>.
     * @throws SAML2Exception if the Response is not valid according to the
     *                        processing rules.
     */
public static Map verifyResponse(final HttpServletRequest httpRequest, final HttpServletResponse httpResponse, final Response response, final String orgName, final String hostEntityId, final String profileBinding) throws SAML2Exception {
    final String method = "SAML2Utils.verifyResponse:";
    if (response == null || orgName == null || orgName.length() == 0) {
        if (debug.messageEnabled()) {
            debug.message(method + "response or orgName is null.");
        }
        throw new SAML2Exception(bundle.getString("nullInput"));
    }
    String respID = response.getID();
    AuthnRequestInfo reqInfo = null;
    String inRespToResp = response.getInResponseTo();
    if (inRespToResp != null && inRespToResp.length() != 0) {
        reqInfo = (AuthnRequestInfo) SPCache.requestHash.get(inRespToResp);
        if (reqInfo == null) {
            if (SAML2FailoverUtils.isSAML2FailoverEnabled()) {
                // Attempt to read AuthnRequestInfoCopy from SAML2 repository
                AuthnRequestInfoCopy reqInfoCopy = null;
                try {
                    reqInfoCopy = (AuthnRequestInfoCopy) SAML2FailoverUtils.retrieveSAML2Token(inRespToResp);
                } catch (SAML2TokenRepositoryException se) {
                    debug.error(method + "AuthnRequestInfoCopy" + " unable to retrieve from SAML2 repository for inResponseTo: " + inRespToResp);
                }
                if (reqInfoCopy != null) {
                    // Get back the AuthnRequestInfo
                    reqInfo = reqInfoCopy.getAuthnRequestInfo(httpRequest, httpResponse);
                    if (debug.messageEnabled()) {
                        debug.message(method + "AuthnRequestInfoCopy" + " retrieved from SAML2 repository for inResponseTo: " + inRespToResp);
                    }
                } else {
                    debug.error(method + "InResponseTo attribute in Response" + " is invalid: " + inRespToResp + ", SAML2 failover is enabled");
                    String[] data = { respID };
                    LogUtil.error(Level.INFO, LogUtil.INVALID_INRESPONSETO_RESPONSE, data, null);
                    throw new SAML2Exception(bundle.getString("invalidInResponseToInResponse"));
                }
            } else {
                AuthnRequestInfoCopy reqInfoCopy = (AuthnRequestInfoCopy) SAML2Store.getTokenFromStore(inRespToResp);
                if (reqInfoCopy != null) {
                    // Get back the AuthnRequestInfo
                    reqInfo = reqInfoCopy.getAuthnRequestInfo(httpRequest, httpResponse);
                    if (debug.messageEnabled()) {
                        debug.message(method + "AuthnRequestInfoCopy" + " retrieved from SAML2 repository for inResponseTo: " + inRespToResp);
                    }
                } else {
                    debug.error(method + "InResponseTo attribute in Response" + " is invalid: " + inRespToResp + ", SAML2 failover is enabled");
                    String[] data = { respID };
                    LogUtil.error(Level.INFO, LogUtil.INVALID_INRESPONSETO_RESPONSE, data, null);
                    throw new SAML2Exception(bundle.getString("invalidInResponseToInResponse"));
                }
            }
        }
    }
    // reqInfo can remain null and will do for IDP initiated SSO requests
    // invoke SP Adapter
    SAML2ServiceProviderAdapter spAdapter = SAML2Utils.getSPAdapterClass(hostEntityId, orgName);
    if (spAdapter != null) {
        AuthnRequest authnRequest = null;
        if (reqInfo != null) {
            authnRequest = reqInfo.getAuthnRequest();
        }
        spAdapter.preSingleSignOnProcess(hostEntityId, orgName, httpRequest, httpResponse, authnRequest, response, profileBinding);
    }
    String idpEntityId = null;
    Issuer respIssuer = response.getIssuer();
    if (respIssuer != null) {
        // optional
        if (!isSourceSiteValid(respIssuer, orgName, hostEntityId)) {
            if (debug.messageEnabled()) {
                debug.message(method + "Issuer in Response is not valid.");
            }
            String[] data = { hostEntityId, orgName, respID };
            LogUtil.error(Level.INFO, LogUtil.INVALID_ISSUER_RESPONSE, data, null);
            throw new SAML2Exception(bundle.getString("invalidIssuerInResponse"));
        } else {
            idpEntityId = respIssuer.getValue();
        }
    }
    Status status = response.getStatus();
    if (status == null || !status.getStatusCode().getValue().equals(SAML2Constants.SUCCESS)) {
        String statusCode = (status == null) ? "" : status.getStatusCode().getValue();
        if (debug.messageEnabled()) {
            debug.message(method + "Response's status code is not success: " + statusCode);
        }
        String[] data = { respID, "" };
        if (LogUtil.isErrorLoggable(Level.FINE)) {
            data[1] = statusCode;
        }
        LogUtil.error(Level.INFO, LogUtil.WRONG_STATUS_CODE, data, null);
        if (SAML2Constants.RESPONDER.equals(statusCode)) {
            //In case of passive authentication the NoPassive response will be sent using two StatusCode nodes:
            //the outer StatusCode will be Responder and the inner StatusCode will contain the NoPassive URN
            StatusCode secondLevelStatusCode = status.getStatusCode().getStatusCode();
            if (secondLevelStatusCode != null && SAML2Constants.NOPASSIVE.equals(secondLevelStatusCode.getValue())) {
                throw new SAML2Exception(SAML2Utils.BUNDLE_NAME, "noPassiveResponse", null);
            }
        } else if (SAML2Constants.REQUESTER.equals(statusCode)) {
            // when is AllowCreate=false mode the auth module gets here with a
            // statusCode of urn:oasis:names:tc:SAML:2.0:status:Requester
            StatusCode secondLevelStatusCode = status.getStatusCode().getStatusCode();
            if (secondLevelStatusCode != null && SAML2Constants.INVALID_NAME_ID_POLICY.equals(secondLevelStatusCode.getValue())) {
                throw new SAML2Exception(SAML2Utils.BUNDLE_NAME, "nameIDMReqInvalidNameIDPolicy", null);
            }
        }
        throw new SAML2Exception(bundle.getString("invalidStatusCodeInResponse"));
    }
    if (saml2MetaManager == null) {
        throw new SAML2Exception(bundle.getString("nullMetaManager"));
    }
    SPSSOConfigElement spConfig = null;
    SPSSODescriptorElement spDesc = null;
    spConfig = saml2MetaManager.getSPSSOConfig(orgName, hostEntityId);
    spDesc = saml2MetaManager.getSPSSODescriptor(orgName, hostEntityId);
    if (debug.messageEnabled()) {
        debug.message(method + "binding is :" + profileBinding);
    }
    // SAML spec processing
    //  4.1.4.3   Verify any signatures present on the assertion(s) or the response
    boolean responseIsSigned = false;
    if (response.isSigned()) {
        IDPSSODescriptorElement idpSSODescriptor = null;
        try {
            idpSSODescriptor = saml2MetaManager.getIDPSSODescriptor(orgName, idpEntityId);
        } catch (SAML2MetaException sme) {
            String[] data = { orgName, idpEntityId };
            LogUtil.error(Level.INFO, LogUtil.IDP_METADATA_ERROR, data, null);
            throw new SAML2Exception(sme);
        }
        if (idpSSODescriptor != null) {
            Set<X509Certificate> verificationCerts = KeyUtil.getVerificationCerts(idpSSODescriptor, idpEntityId, SAML2Constants.IDP_ROLE);
            if (CollectionUtils.isEmpty(verificationCerts) || !response.isSignatureValid(verificationCerts)) {
                debug.error(method + "Response is not signed or signature is not valid.");
                String[] data = { orgName, hostEntityId, idpEntityId };
                LogUtil.error(Level.INFO, LogUtil.POST_RESPONSE_INVALID_SIGNATURE, data, null);
                throw new SAML2Exception(bundle.getString("invalidSignInResponse"));
            }
        } else {
            String[] data = { idpEntityId };
            LogUtil.error(Level.INFO, LogUtil.IDP_METADATA_ERROR, data, null);
            throw new SAML2Exception(SAML2Utils.bundle.getString("metaDataError"));
        }
        responseIsSigned = true;
    }
    if (debug.messageEnabled()) {
        debug.message(method + "responseIsSigned is :" + responseIsSigned);
    }
    // assertion encryption check
    boolean needAssertionEncrypted = false;
    String assertionEncryptedAttr = getAttributeValueFromSPSSOConfig(spConfig, SAML2Constants.WANT_ASSERTION_ENCRYPTED);
    needAssertionEncrypted = Boolean.parseBoolean(assertionEncryptedAttr);
    if (debug.messageEnabled()) {
        debug.message(method + "NeedAssertionEncrypted is :" + needAssertionEncrypted);
    }
    List<Assertion> assertions = response.getAssertion();
    if (needAssertionEncrypted && !CollectionUtils.isEmpty(assertions)) {
        String[] data = { respID };
        LogUtil.error(Level.INFO, LogUtil.ASSERTION_NOT_ENCRYPTED, data, null);
        throw new SAML2Exception(SAML2Utils.bundle.getString("assertionNotEncrypted"));
    }
    Set<PrivateKey> decryptionKeys;
    List<EncryptedAssertion> encAssertions = response.getEncryptedAssertion();
    if (encAssertions != null) {
        decryptionKeys = KeyUtil.getDecryptionKeys(spConfig);
        for (EncryptedAssertion encAssertion : encAssertions) {
            Assertion assertion = encAssertion.decrypt(decryptionKeys);
            if (assertions == null) {
                assertions = new ArrayList<>();
            }
            assertions.add(assertion);
        }
    }
    if (CollectionUtils.isEmpty(assertions)) {
        if (debug.messageEnabled()) {
            debug.message(method + "no assertion in the Response.");
        }
        String[] data = { respID };
        LogUtil.error(Level.INFO, LogUtil.MISSING_ASSERTION, data, null);
        throw new SAML2Exception(SAML2Utils.bundle.getString("missingAssertion"));
    }
    boolean wantAssertionsSigned = spDesc.isWantAssertionsSigned();
    if (debug.messageEnabled()) {
        debug.message(method + "wantAssertionsSigned is :" + wantAssertionsSigned);
    }
    // validate the assertions
    Map smap = null;
    Map bearerMap = null;
    IDPSSODescriptorElement idp = null;
    Set<X509Certificate> verificationCerts = null;
    boolean allAssertionsSigned = true;
    for (Assertion assertion : assertions) {
        String assertionID = assertion.getID();
        Issuer issuer = assertion.getIssuer();
        if (!isSourceSiteValid(issuer, orgName, hostEntityId)) {
            debug.error("assertion's source site is not valid.");
            String[] data = { assertionID };
            LogUtil.error(Level.INFO, LogUtil.INVALID_ISSUER_ASSERTION, data, null);
            throw new SAML2Exception(bundle.getString("invalidIssuerInAssertion"));
        }
        if (idpEntityId == null) {
            idpEntityId = issuer.getValue();
        } else {
            if (!idpEntityId.equals(issuer.getValue())) {
                if (debug.messageEnabled()) {
                    debug.message(method + "Issuer in Assertion doesn't " + "match the Issuer in Response or other " + "Assertions in the Response.");
                }
                String[] data = { assertionID };
                LogUtil.error(Level.INFO, LogUtil.MISMATCH_ISSUER_ASSERTION, data, null);
                throw new SAML2Exception(SAML2Utils.bundle.getString("mismatchIssuer"));
            }
        }
        if (assertion.isSigned()) {
            if (verificationCerts == null) {
                idp = saml2MetaManager.getIDPSSODescriptor(orgName, idpEntityId);
                verificationCerts = KeyUtil.getVerificationCerts(idp, idpEntityId, SAML2Constants.IDP_ROLE);
            }
            if (CollectionUtils.isEmpty(verificationCerts) || !assertion.isSignatureValid(verificationCerts)) {
                debug.error(method + "Assertion is not signed or signature is not valid.");
                String[] data = { assertionID };
                LogUtil.error(Level.INFO, LogUtil.INVALID_SIGNATURE_ASSERTION, data, null);
                throw new SAML2Exception(bundle.getString("invalidSignatureOnAssertion"));
            }
        } else {
            allAssertionsSigned = false;
        }
        List authnStmts = assertion.getAuthnStatements();
        if (authnStmts != null && !authnStmts.isEmpty()) {
            Subject subject = assertion.getSubject();
            if (subject == null) {
                continue;
            }
            List subjectConfirms = subject.getSubjectConfirmation();
            if (subjectConfirms == null || subjectConfirms.isEmpty()) {
                continue;
            }
            bearerMap = isBearerSubjectConfirmation(subjectConfirms, inRespToResp, spDesc, spConfig, assertionID);
            if (!((Boolean) bearerMap.get(SAML2Constants.IS_BEARER))) {
                continue;
            }
            boolean foundAssertion = false;
            if ((SPCache.assertionByIDCache != null) && (SPCache.assertionByIDCache.containsKey(assertionID))) {
                foundAssertion = true;
            }
            if ((!foundAssertion) && SAML2FailoverUtils.isSAML2FailoverEnabled()) {
                try {
                    if (SAML2FailoverUtils.retrieveSAML2Token(assertionID) != null) {
                        foundAssertion = true;
                    }
                } catch (SAML2TokenRepositoryException e) {
                    if (debug.messageEnabled()) {
                        debug.message("Session not found in AMTokenSAML2Repository.", e);
                    }
                }
            }
            if (foundAssertion) {
                debug.error("Bearer Assertion is one time use only!");
                throw new SAML2Exception(bundle.getString("usedBearAssertion"));
            }
            checkAudience(assertion.getConditions(), hostEntityId, assertionID);
            if (smap == null) {
                smap = fillMap(authnStmts, subject, assertion, assertions, reqInfo, inRespToResp, orgName, hostEntityId, idpEntityId, spConfig, (Date) bearerMap.get(SAML2Constants.NOTONORAFTER));
            }
        }
    // end of having authnStmt
    }
    if (smap == null) {
        debug.error("No Authentication Assertion in Response.");
        throw new SAML2Exception(bundle.getString("missingAuthnAssertion"));
    }
    // the enclosing element
    if (wantAssertionsSigned && !(responseIsSigned || allAssertionsSigned)) {
        debug.error(method + "WantAssertionsSigned is true and response or all assertions are not signed");
        String[] data = { orgName, hostEntityId, idpEntityId };
        LogUtil.error(Level.INFO, LogUtil.INVALID_SIGNATURE_ASSERTION, data, null);
        throw new SAML2Exception(bundle.getString("assertionNotSigned"));
    }
    // signing each individual <Assertion> element or by signing the <Response> element.
    if (profileBinding.equals(SAML2Constants.HTTP_POST)) {
        boolean wantPostResponseSigned = SAML2Utils.wantPOSTResponseSigned(orgName, hostEntityId, SAML2Constants.SP_ROLE);
        if (debug.messageEnabled()) {
            debug.message(method + "wantPostResponseSigned is :" + wantPostResponseSigned);
        }
        if (wantPostResponseSigned && !responseIsSigned) {
            debug.error(method + "wantPostResponseSigned is true but response is not signed");
            String[] data = { orgName, hostEntityId, idpEntityId };
            LogUtil.error(Level.INFO, LogUtil.POST_RESPONSE_INVALID_SIGNATURE, data, null);
            throw new SAML2Exception(bundle.getString("responseNotSigned"));
        }
        if (!responseIsSigned && !allAssertionsSigned) {
            debug.error(method + "WantAssertionsSigned is true but some or all assertions are not signed");
            String[] data = { orgName, hostEntityId, idpEntityId };
            LogUtil.error(Level.INFO, LogUtil.INVALID_SIGNATURE_ASSERTION, data, null);
            throw new SAML2Exception(bundle.getString("assertionNotSigned"));
        }
    }
    return smap;
}
Also used : PrivateKey(java.security.PrivateKey) Issuer(com.sun.identity.saml2.assertion.Issuer) AuthnRequestInfo(com.sun.identity.saml2.profile.AuthnRequestInfo) SPSSODescriptorElement(com.sun.identity.saml2.jaxb.metadata.SPSSODescriptorElement) StatusCode(com.sun.identity.saml2.protocol.StatusCode) ArrayList(java.util.ArrayList) List(java.util.List) AuthnRequestInfoCopy(com.sun.identity.saml2.profile.AuthnRequestInfoCopy) SAML2ServiceProviderAdapter(com.sun.identity.saml2.plugins.SAML2ServiceProviderAdapter) SAML2MetaException(com.sun.identity.saml2.meta.SAML2MetaException) Status(com.sun.identity.saml2.protocol.Status) SPSSOConfigElement(com.sun.identity.saml2.jaxb.entityconfig.SPSSOConfigElement) EncryptedAssertion(com.sun.identity.saml2.assertion.EncryptedAssertion) Assertion(com.sun.identity.saml2.assertion.Assertion) X509Certificate(java.security.cert.X509Certificate) Subject(com.sun.identity.saml2.assertion.Subject) Date(java.util.Date) AuthnRequest(com.sun.identity.saml2.protocol.AuthnRequest) EncryptedAssertion(com.sun.identity.saml2.assertion.EncryptedAssertion) SAML2TokenRepositoryException(org.forgerock.openam.federation.saml2.SAML2TokenRepositoryException) Map(java.util.Map) HashMap(java.util.HashMap) IDPSSODescriptorElement(com.sun.identity.saml2.jaxb.metadata.IDPSSODescriptorElement)

Example 5 with SAML2ServiceProviderAdapter

use of com.sun.identity.saml2.plugins.SAML2ServiceProviderAdapter in project OpenAM by OpenRock.

the class SAML2Utils method getSPAdapterClass.

/**
     * Returns an <code>SP</code> adapter class
     *
     * @param spEntityID the entity id of the service provider
     * @param realm      the realm name
     * @return the <code>SP</code> adapter class
     * @throws SAML2Exception if the operation is not successful
     */
public static SAML2ServiceProviderAdapter getSPAdapterClass(String spEntityID, String realm) throws SAML2Exception {
    String classMethod = "SAML2Utils.getSPAdapterClass: ";
    if (debug.messageEnabled()) {
        debug.message(classMethod + "get SPAdapter for " + spEntityID + " under realm " + realm);
    }
    String spAdapterClassName = null;
    SAML2ServiceProviderAdapter spAdapterClass = null;
    try {
        spAdapterClassName = getAttributeValueFromSSOConfig(realm, spEntityID, SAML2Constants.SP_ROLE, SAML2Constants.SP_ADAPTER_CLASS);
        if (debug.messageEnabled()) {
            debug.message(classMethod + "get SPAdapter class " + spAdapterClassName);
        }
        if ((spAdapterClassName != null) && (spAdapterClassName.length() != 0)) {
            spAdapterClass = (SAML2ServiceProviderAdapter) SPCache.spAdapterClassCache.get(realm + spEntityID + spAdapterClassName);
            if (spAdapterClass == null) {
                spAdapterClass = (SAML2ServiceProviderAdapter) Class.forName(spAdapterClassName).newInstance();
                List env = getAllAttributeValueFromSSOConfig(realm, spEntityID, SAML2Constants.SP_ROLE, SAML2Constants.SP_ADAPTER_ENV);
                Map map = parseEnvList(env);
                map.put(SAML2ServiceProviderAdapter.HOSTED_ENTITY_ID, spEntityID);
                map.put(SAML2ServiceProviderAdapter.REALM, realm);
                spAdapterClass.initialize(map);
                SPCache.spAdapterClassCache.put(realm + spEntityID + spAdapterClassName, spAdapterClass);
                if (debug.messageEnabled()) {
                    debug.message(classMethod + "create new SPAdapter " + spAdapterClassName + " for " + spEntityID + " under realm " + realm);
                }
            } else {
                if (debug.messageEnabled()) {
                    debug.message(classMethod + "got the SPAdapter " + spAdapterClassName + " from cache");
                }
            }
        }
    } catch (InstantiationException ex) {
        debug.error(classMethod + "Unable to get SP Adapter class instance.", ex);
        throw new SAML2Exception(ex);
    } catch (ClassNotFoundException ex) {
        debug.error(classMethod + "SP Adapter class not found.", ex);
        throw new SAML2Exception(ex);
    } catch (IllegalAccessException ex) {
        debug.error(classMethod + "Unable to get SP Adapter class.", ex);
        throw new SAML2Exception(ex);
    }
    return spAdapterClass;
}
Also used : ArrayList(java.util.ArrayList) List(java.util.List) SAML2ServiceProviderAdapter(com.sun.identity.saml2.plugins.SAML2ServiceProviderAdapter) Map(java.util.Map) HashMap(java.util.HashMap)

Aggregations

SAML2ServiceProviderAdapter (com.sun.identity.saml2.plugins.SAML2ServiceProviderAdapter)8 AuthnRequest (com.sun.identity.saml2.protocol.AuthnRequest)7 SAML2Exception (com.sun.identity.saml2.common.SAML2Exception)5 SPSSODescriptorElement (com.sun.identity.saml2.jaxb.metadata.SPSSODescriptorElement)5 SAML2MetaException (com.sun.identity.saml2.meta.SAML2MetaException)5 ArrayList (java.util.ArrayList)5 List (java.util.List)5 Map (java.util.Map)5 SAML2TokenRepositoryException (org.forgerock.openam.federation.saml2.SAML2TokenRepositoryException)5 SPSSOConfigElement (com.sun.identity.saml2.jaxb.entityconfig.SPSSOConfigElement)4 IDPSSODescriptorElement (com.sun.identity.saml2.jaxb.metadata.IDPSSODescriptorElement)4 PrivateKey (java.security.PrivateKey)3 HashMap (java.util.HashMap)3 SessionException (com.sun.identity.plugin.session.SessionException)2 Assertion (com.sun.identity.saml2.assertion.Assertion)2 Subject (com.sun.identity.saml2.assertion.Subject)2 IDPList (com.sun.identity.saml2.protocol.IDPList)2 Iterator (java.util.Iterator)2 PAOSException (com.sun.identity.liberty.ws.paos.PAOSException)1 PAOSRequest (com.sun.identity.liberty.ws.paos.PAOSRequest)1