Search in sources :

Example 46 with Response

use of com.sun.identity.saml2.protocol.Response in project OpenAM by OpenRock.

the class SAML2Proxy method getUrl.

private static String getUrl(HttpServletRequest request, HttpServletResponse response) throws IOException {
    if (request == null || response == null) {
        DEBUG.error("SAML2Proxy: Null request or response");
        return getUrlWithError(request, BAD_REQUEST);
    }
    try {
        SAMLUtils.checkHTTPContentLength(request);
    } catch (ServletException se) {
        DEBUG.error("SAML2Proxy: content length too large");
        return getUrlWithError(request, BAD_REQUEST);
    }
    if (FSUtils.needSetLBCookieAndRedirect(request, response, false)) {
        return getUrlWithError(request, MISSING_COOKIE);
    }
    // get entity id and orgName
    String requestURL = request.getRequestURL().toString();
    String metaAlias = SAML2MetaUtils.getMetaAliasByUri(requestURL);
    SAML2MetaManager metaManager = SAML2Utils.getSAML2MetaManager();
    String hostEntityId;
    if (metaManager == null) {
        DEBUG.error("SAML2Proxy: Unable to obtain metaManager");
        return getUrlWithError(request, MISSING_META_MANAGER);
    }
    try {
        hostEntityId = metaManager.getEntityByMetaAlias(metaAlias);
        if (hostEntityId == null) {
            throw new SAML2MetaException("Caught Instantly");
        }
    } catch (SAML2MetaException sme) {
        DEBUG.warning("SAML2Proxy: unable to find hosted entity with metaAlias: {} Exception: {}", metaAlias, sme.toString());
        return getUrlWithError(request, META_DATA_ERROR);
    }
    String realm = SAML2MetaUtils.getRealmByMetaAlias(metaAlias);
    if (StringUtils.isEmpty(realm)) {
        realm = "/";
    }
    ResponseInfo respInfo;
    try {
        respInfo = SPACSUtils.getResponse(request, response, realm, hostEntityId, metaManager);
    } catch (SAML2Exception se) {
        DEBUG.error("SAML2Proxy: Unable to obtain SAML response", se);
        return getUrlWithError(request, SAML_GET_RESPONSE_ERROR, se.getL10NMessage(request.getLocale()));
    }
    Map smap;
    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) {
        DEBUG.error("SAML2Proxy: An error occurred while verifying the SAML response", se);
        return getUrlWithError(request, SAML_VERIFY_RESPONSE_ERROR, se.getL10NMessage(request.getLocale()));
    }
    String key = generateKey();
    //survival time is one hour
    SAML2ResponseData data = new SAML2ResponseData((String) smap.get(SAML2Constants.SESSION_INDEX), (Subject) smap.get(SAML2Constants.SUBJECT), (Assertion) smap.get(SAML2Constants.POST_ASSERTION), respInfo);
    if (SAML2FailoverUtils.isSAML2FailoverEnabled()) {
        try {
            //counted in seconds
            long sessionExpireTime = System.currentTimeMillis() / 1000 + SPCache.interval;
            SAML2FailoverUtils.saveSAML2TokenWithoutSecondaryKey(key, data, sessionExpireTime);
        } catch (SAML2TokenRepositoryException e) {
            DEBUG.error("An error occurred while persisting the SAML token", e);
            return getUrlWithError(request, SAML_FAILOVER_DISABLED_ERROR);
        }
    } else {
        SAML2Store.saveTokenWithKey(key, data);
    }
    return getUrlWithKey(request, key);
}
Also used : ServletException(javax.servlet.ServletException) ResponseInfo(com.sun.identity.saml2.profile.ResponseInfo) SAML2Exception(com.sun.identity.saml2.common.SAML2Exception) SAML2TokenRepositoryException(org.forgerock.openam.federation.saml2.SAML2TokenRepositoryException) SAML2MetaManager(com.sun.identity.saml2.meta.SAML2MetaManager) SAML2MetaException(com.sun.identity.saml2.meta.SAML2MetaException) Map(java.util.Map)

Example 47 with Response

use of com.sun.identity.saml2.protocol.Response in project OpenAM by OpenRock.

the class SAML2 method initiateSAMLLoginAtIDP.

/**
     * Performs similar to SPSSOFederate.initiateAuthnRequest by returning to the next auth stage
     * with a redirect (either GET or POST depending on the config) which triggers remote IdP authentication.
     */
private int initiateSAMLLoginAtIDP(final HttpServletResponse response, final HttpServletRequest request) throws SAML2Exception, AuthLoginException {
    if (reqBinding == null) {
        reqBinding = SAML2Constants.HTTP_REDIRECT;
    }
    final String spEntityID = SPSSOFederate.getSPEntityId(metaAlias);
    final IDPSSODescriptorElement idpsso = SPSSOFederate.getIDPSSOForAuthnReq(realm, entityName);
    final SPSSODescriptorElement spsso = SPSSOFederate.getSPSSOForAuthnReq(realm, spEntityID);
    if (idpsso == null || spsso == null) {
        return processError(bundle.getString("samlLocalConfigFailed"), "SAML2 :: initiateSAMLLoginAtIDP() : {}", bundle.getString("samlLocalConfigFailed"));
    }
    final String ssoURL = SPSSOFederate.getSSOURL(idpsso.getSingleSignOnService(), reqBinding);
    final List extensionsList = SPSSOFederate.getExtensionsList(spEntityID, realm);
    final Map<String, Collection<String>> spConfigAttrsMap = SPSSOFederate.getAttrsMapForAuthnReq(realm, spEntityID);
    authnRequest = SPSSOFederate.createAuthnRequest(realm, spEntityID, params, spConfigAttrsMap, extensionsList, spsso, idpsso, ssoURL, false);
    final AuthnRequestInfo reqInfo = new AuthnRequestInfo(request, response, realm, spEntityID, null, authnRequest, null, params);
    synchronized (SPCache.requestHash) {
        SPCache.requestHash.put(authnRequest.getID(), reqInfo);
    }
    saveAuthnRequest(authnRequest, reqInfo);
    final Callback[] nextCallbacks = getCallback(REDIRECT);
    final RedirectCallback redirectCallback = (RedirectCallback) nextCallbacks[0];
    setCookiesForRedirects(request, response);
    //we only handle Redirect and POST
    if (SAML2Constants.HTTP_POST.equals(reqBinding)) {
        final String postMsg = SPSSOFederate.getPostBindingMsg(idpsso, spsso, spConfigAttrsMap, authnRequest);
        configurePostRedirectCallback(postMsg, ssoURL, redirectCallback);
    } else {
        final String authReqXMLString = authnRequest.toXMLString(true, true);
        final String redirectUrl = SPSSOFederate.getRedirect(authReqXMLString, null, ssoURL, idpsso, spsso, spConfigAttrsMap);
        configureGetRedirectCallback(redirectUrl, redirectCallback);
    }
    return REDIRECT;
}
Also used : RedirectCallback(com.sun.identity.authentication.spi.RedirectCallback) Callback(javax.security.auth.callback.Callback) PagePropertiesCallback(com.sun.identity.authentication.spi.PagePropertiesCallback) RedirectCallback(com.sun.identity.authentication.spi.RedirectCallback) SPSSODescriptorElement(com.sun.identity.saml2.jaxb.metadata.SPSSODescriptorElement) AuthnRequestInfo(com.sun.identity.saml2.profile.AuthnRequestInfo) Collection(java.util.Collection) List(java.util.List) IDPSSODescriptorElement(com.sun.identity.saml2.jaxb.metadata.IDPSSODescriptorElement)

Example 48 with Response

use of com.sun.identity.saml2.protocol.Response in project OpenAM by OpenRock.

the class IDPSingleLogout method processLogoutRequest.

/**
     * Gets and processes the Single <code>LogoutRequest</code> from SP
     * and return <code>LogoutResponse</code>.
     *
     * @param logoutReq <code>LogoutRequest</code> from SP
     * @param request the HttpServletRequest.
     * @param response the HttpServletResponse.
     * @param binding name of binding will be used for request processing.
     * @param relayState the relay state.
     * @param idpEntityID name of host entity ID.
     * @param realm name of host entity.
     * @param isVerified true if the request is verified already.
     * @return LogoutResponse the target URL on successful
     * <code>LogoutRequest</code>.
     * @throws SAML2Exception if error processing
     *          <code>LogoutRequest</code>.
     */
public static LogoutResponse processLogoutRequest(LogoutRequest logoutReq, HttpServletRequest request, HttpServletResponse response, String binding, String relayState, String idpEntityID, String realm, boolean isVerified) throws SAML2Exception {
    Status status = null;
    String spEntity = logoutReq.getIssuer().getValue();
    Object session = null;
    String tmpStr = request.getParameter("isLBReq");
    boolean isLBReq = (tmpStr == null || !tmpStr.equals("false"));
    try {
        do {
            String requestId = logoutReq.getID();
            SAML2Utils.verifyRequestIssuer(realm, idpEntityID, logoutReq.getIssuer(), requestId);
            List siList = logoutReq.getSessionIndex();
            if (siList == null) {
                debug.error("IDPSingleLogout.processLogoutRequest: " + "session index are null in logout request");
                status = SAML2Utils.generateStatus(SAML2Constants.REQUESTER, "");
                break;
            }
            int numSI = siList.size();
            // TODO : handle list of session index
            Iterator siIter = siList.iterator();
            String sessionIndex = null;
            if (siIter.hasNext()) {
                sessionIndex = (String) siIter.next();
            }
            if (debug.messageEnabled()) {
                debug.message("IDPLogoutUtil.processLogoutRequest: " + "idpEntityID=" + idpEntityID + ", sessionIndex=" + sessionIndex);
            }
            if (sessionIndex == null) {
                // this case won't happen
                // according to the spec: SP has to send at least
                // one sessionIndex, could be multiple (TODO: need
                // to handle that above; but when IDP sends out
                // logout request, it could omit sessionIndex list,
                // which means all sessions on SP side, so SP side
                // needs to care about this case
                debug.error("IDPLogoutUtil.processLogoutRequest: " + "No session index in logout request");
                status = SAML2Utils.generateStatus(SAML2Constants.REQUESTER, "");
                break;
            }
            String remoteServiceURL = null;
            if (isLBReq) {
                // server id is the last two digit of the session index
                String serverId = sessionIndex.substring(sessionIndex.length() - 2);
                if (debug.messageEnabled()) {
                    debug.message("IDPSingleLogout.processLogoutRequest: " + "sessionIndex=" + sessionIndex + ", id=" + serverId);
                }
                // find out remote serice URL based on server id
                remoteServiceURL = SAML2Utils.getRemoteServiceURL(serverId);
            }
            IDPSession idpSession = IDPCache.idpSessionsByIndices.get(sessionIndex);
            if (idpSession == null && SAML2FailoverUtils.isSAML2FailoverEnabled()) {
                // Read from SAML2 Token Repository
                IDPSessionCopy idpSessionCopy = null;
                try {
                    idpSessionCopy = (IDPSessionCopy) SAML2FailoverUtils.retrieveSAML2Token(sessionIndex);
                } catch (SAML2TokenRepositoryException se) {
                    debug.error("IDPSingleLogout.processLogoutRequest: Error while deleting token from " + "SAML2 Token Repository for sessionIndex:" + sessionIndex, se);
                }
                // Copy back to IDPSession
                if (idpSessionCopy != null) {
                    idpSession = new IDPSession(idpSessionCopy);
                } else {
                    SAML2Utils.debug.error("IDPSessionCopy is NULL!!!");
                }
            }
            if (idpSession == null) {
                // peer then we have to route the request.
                if (remoteServiceURL != null) {
                    boolean peerError = false;
                    String remoteLogoutURL = remoteServiceURL + SAML2Utils.removeDeployUri(request.getRequestURI());
                    String queryString = request.getQueryString();
                    if (queryString == null) {
                        remoteLogoutURL = remoteLogoutURL + "?isLBReq=false";
                    } else {
                        remoteLogoutURL = remoteLogoutURL + "?" + queryString + "&isLBReq=false";
                    }
                    LogoutResponse logoutRes = LogoutUtil.forwardToRemoteServer(logoutReq, remoteLogoutURL);
                    if ((logoutRes != null) && !isNameNotFound(logoutRes)) {
                        if ((isSuccess(logoutRes)) && (numSI > 0)) {
                            siList = LogoutUtil.getSessionIndex(logoutRes);
                            if (siList == null || siList.isEmpty()) {
                                peerError = false;
                                break;
                            }
                        }
                    } else {
                        peerError = true;
                    }
                    if (peerError || (siList != null && siList.size() > 0)) {
                        status = PARTIAL_LOGOUT_STATUS;
                        break;
                    } else {
                        status = SUCCESS_STATUS;
                        break;
                    }
                } else {
                    debug.error("IDPLogoutUtil.processLogoutRequest: " + "IDP no longer has this session index " + sessionIndex);
                    status = SAML2Utils.generateStatus(SAML2Constants.RESPONDER, SAML2Utils.bundle.getString("invalidSessionIndex"));
                    break;
                }
            } else {
                // signature.
                if (!isVerified && !LogoutUtil.verifySLORequest(logoutReq, realm, logoutReq.getIssuer().getValue(), idpEntityID, SAML2Constants.IDP_ROLE)) {
                    throw new SAML2Exception(SAML2Utils.bundle.getString("invalidSignInRequest"));
                }
            }
            session = idpSession.getSession();
            // handle external application logout if configured
            BaseConfigType idpConfig = SAML2Utils.getSAML2MetaManager().getIDPSSOConfig(realm, idpEntityID);
            List appLogoutURL = (List) SAML2MetaUtils.getAttributes(idpConfig).get(SAML2Constants.APP_LOGOUT_URL);
            if (debug.messageEnabled()) {
                debug.message("IDPLogoutUtil.processLogoutRequest: " + "external app logout URL= " + appLogoutURL);
            }
            if ((appLogoutURL != null) && (appLogoutURL.size() != 0)) {
                SAML2Utils.postToAppLogout(request, (String) appLogoutURL.get(0), session);
            }
            List<NameIDandSPpair> list = idpSession.getNameIDandSPpairs();
            int n = list.size();
            if (debug.messageEnabled()) {
                debug.message("IDPLogoutUtil.processLogoutRequest: " + "NameIDandSPpair for " + sessionIndex + " is " + list + ", size=" + n);
            }
            NameIDandSPpair pair = null;
            // remove sending SP from the list
            String spIssuer = logoutReq.getIssuer().getValue();
            for (int i = 0; i < n; i++) {
                pair = list.get(i);
                if (pair.getSPEntityID().equals(spIssuer)) {
                    list.remove(i);
                    removeTransientNameIDFromCache(pair.getNameID());
                    break;
                }
            }
            List partners = idpSession.getSessionPartners();
            boolean cleanUp = true;
            if (partners != null && !partners.isEmpty()) {
                cleanUp = false;
            }
            n = list.size();
            if (n == 0) {
                // this is the case where there is no other
                // session participant
                status = destroyTokenAndGenerateStatus(sessionIndex, idpSession.getSession(), request, response, cleanUp);
                if (cleanUp) {
                    IDPCache.idpSessionsByIndices.remove(sessionIndex);
                    if ((agent != null) && agent.isRunning() && (saml2Svc != null)) {
                        saml2Svc.setIdpSessionCount((long) IDPCache.idpSessionsByIndices.size());
                    }
                    if (SAML2FailoverUtils.isSAML2FailoverEnabled()) {
                        try {
                            SAML2FailoverUtils.deleteSAML2Token(sessionIndex);
                        } catch (SAML2TokenRepositoryException se) {
                            debug.error("IDPSingleLogout.processLogoutRequest: Error while deleting token from " + "SAML2 Token Repository for sessionIndex:" + sessionIndex, se);
                        }
                    }
                    IDPCache.authnContextCache.remove(sessionIndex);
                }
                break;
            }
            //We should save the originally used request binding to make sure the response is sent back using the
            //correct binding.
            idpSession.setOriginatingLogoutRequestBinding(binding);
            // there are other SPs to be logged out
            if (binding.equals(SAML2Constants.HTTP_REDIRECT) || binding.equals(SAML2Constants.HTTP_POST)) {
                idpSession.setOriginatingLogoutRequestID(logoutReq.getID());
                idpSession.setOriginatingLogoutSPEntityID(logoutReq.getIssuer().getValue());
            }
            int soapFailCount = 0;
            for (int i = 0; i < n; i++) {
                pair = list.remove(0);
                removeTransientNameIDFromCache(pair.getNameID());
                String spEntityID = pair.getSPEntityID();
                if (debug.messageEnabled()) {
                    debug.message("IDPSingleLogout.processLogoutRequest: SP for " + sessionIndex + " is " + spEntityID);
                }
                List<SingleLogoutServiceElement> slosList = getSPSLOServiceEndpoints(realm, spEntityID);
                // get IDP entity config in case of SOAP,for basic auth info
                SPSSOConfigElement spConfig = null;
                spConfig = SAML2Utils.getSAML2MetaManager().getSPSSOConfig(realm, spEntityID);
                String uri = request.getRequestURI();
                String metaAlias = SAML2MetaUtils.getMetaAliasByUri(uri);
                HashMap paramsMap = new HashMap();
                paramsMap.put(SAML2Constants.ROLE, SAML2Constants.IDP_ROLE);
                StringBuffer requestID = null;
                SingleLogoutServiceElement logoutEndpoint = LogoutUtil.getMostAppropriateSLOServiceLocation(slosList, idpSession.getOriginatingLogoutRequestBinding());
                if (logoutEndpoint == null) {
                    continue;
                }
                try {
                    requestID = LogoutUtil.doLogout(metaAlias, spEntityID, null, logoutEndpoint, relayState, sessionIndex, pair.getNameID(), request, response, paramsMap, spConfig);
                } catch (SAML2Exception ex) {
                    if (logoutEndpoint.getBinding().equals(SAML2Constants.SOAP)) {
                        debug.error("IDPSingleLogout.initiateLogoutRequest:", ex);
                        soapFailCount++;
                        continue;
                    } else {
                        throw ex;
                    }
                }
                String bindingUsed = logoutEndpoint.getBinding();
                if (bindingUsed.equals(SAML2Constants.HTTP_REDIRECT) || bindingUsed.equals(SAML2Constants.HTTP_POST)) {
                    String requestIDStr = requestID.toString();
                    if (requestIDStr != null && requestIDStr.length() != 0) {
                        idpSession.setPendingLogoutRequestID(requestIDStr);
                    }
                    return null;
                }
            }
            if (soapFailCount == n) {
                throw new SAML2Exception(SAML2Utils.bundle.getString("sloFailed"));
            } else if (soapFailCount > 0) {
                throw new SAML2Exception(SAML2Utils.bundle.getString("partialLogout"));
            }
            spEntity = idpSession.getOriginatingLogoutSPEntityID();
            if (binding.equals(SAML2Constants.HTTP_REDIRECT) || binding.equals(SAML2Constants.HTTP_POST)) {
                sendLastResponse(idpSession, null, request, response, sessionIndex, session, realm, idpEntityID, relayState);
                return null;
            } else {
                // binding is SOAP, generate logout response
                // and send to initiating SP
                status = destroyTokenAndGenerateStatus(sessionIndex, idpSession.getSession(), request, response, true);
                if (cleanUp) {
                    IDPCache.idpSessionsByIndices.remove(sessionIndex);
                    if ((agent != null) && agent.isRunning() && (saml2Svc != null)) {
                        saml2Svc.setIdpSessionCount((long) IDPCache.idpSessionsByIndices.size());
                    }
                    if (SAML2FailoverUtils.isSAML2FailoverEnabled()) {
                        try {
                            SAML2FailoverUtils.deleteSAML2Token(sessionIndex);
                        } catch (SAML2TokenRepositoryException se) {
                            debug.error("IDPSingleLogout.processLogoutRequest: Error while deleting token from " + "SAML2 Token Repository for sessionIndex:" + sessionIndex, se);
                        }
                    }
                    IDPCache.authnContextCache.remove(sessionIndex);
                }
            }
        } while (false);
    } catch (SessionException ssoe) {
        debug.error("IDPSingleLogout.processLogoutRequest: unable to get meta for ", ssoe);
        status = SAML2Utils.generateStatus(idpEntityID, ssoe.toString());
    } catch (SAML2Exception e) {
        // show throw exception
        e.printStackTrace();
        SAML2Utils.debug.error("DB ERROR!!!");
    }
    // process multi-federation protocol
    boolean isMultiProtocol = false;
    try {
        SessionProvider provider = SessionManager.getProvider();
        if ((session != null) && (provider.isValid(session)) && MultiProtocolUtils.isMultipleProtocolSession(session, SingleLogoutManager.SAML2)) {
            isMultiProtocol = true;
        }
    } catch (SessionException ex) {
    //ignore
    }
    //here we are providing null for remote entity, because it's an unused variable in the method...
    LogoutResponse logRes = LogoutUtil.generateResponse(status, logoutReq.getID(), SAML2Utils.createIssuer(idpEntityID), realm, SAML2Constants.IDP_ROLE, null);
    if (!isMultiProtocol) {
        return logRes;
    } else {
        try {
            Set set = new HashSet();
            set.add(session);
            String sessUser = SessionManager.getProvider().getPrincipalName(session);
            boolean isSOAPInitiated = binding.equals(SAML2Constants.SOAP);
            SingleLogoutServiceElement endpoint = getLogoutResponseEndpoint(realm, spEntity, binding);
            String location = getResponseLocation(endpoint);
            logRes.setDestination(XMLUtils.escapeSpecialCharacters(location));
            debug.message("IDPSingleLogout.processLogReq : call MP");
            int retStat = SingleLogoutManager.getInstance().doIDPSingleLogout(set, sessUser, request, response, isSOAPInitiated, false, SingleLogoutManager.SAML2, realm, idpEntityID, spEntity, relayState, logoutReq.toXMLString(true, true), logRes.toXMLString(true, true), SingleLogoutManager.LOGOUT_SUCCEEDED_STATUS);
            if (retStat != SingleLogoutManager.LOGOUT_REDIRECTED_STATUS) {
                logRes = updateLogoutResponse(logRes, retStat);
                return logRes;
            } else {
                return null;
            }
        } catch (SessionException ex) {
            debug.error("IDPSingleLogout.ProcessLogoutRequest: SP " + "initiated SOAP logout", ex);
            throw new SAML2Exception(ex.getMessage());
        } catch (Exception ex) {
            debug.error("IDPSingleLogout.ProcessLogoutRequest: SP " + "initiated SOAP logout (MP)", ex);
            throw new SAML2Exception(ex.getMessage());
        }
    }
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) HashMap(java.util.HashMap) SessionException(com.sun.identity.plugin.session.SessionException) BaseConfigType(com.sun.identity.saml2.jaxb.entityconfig.BaseConfigType) SingleLogoutServiceElement(com.sun.identity.saml2.jaxb.metadata.SingleLogoutServiceElement) Iterator(java.util.Iterator) List(java.util.List) SessionProvider(com.sun.identity.plugin.session.SessionProvider) HashSet(java.util.HashSet) Status(com.sun.identity.saml2.protocol.Status) LogoutResponse(com.sun.identity.saml2.protocol.LogoutResponse) SPSSOConfigElement(com.sun.identity.saml2.jaxb.entityconfig.SPSSOConfigElement) SessionException(com.sun.identity.plugin.session.SessionException) SAML2MetaException(com.sun.identity.saml2.meta.SAML2MetaException) SAML2TokenRepositoryException(org.forgerock.openam.federation.saml2.SAML2TokenRepositoryException) IOException(java.io.IOException) SAML2Exception(com.sun.identity.saml2.common.SAML2Exception) SAML2Exception(com.sun.identity.saml2.common.SAML2Exception) SAML2TokenRepositoryException(org.forgerock.openam.federation.saml2.SAML2TokenRepositoryException)

Example 49 with Response

use of com.sun.identity.saml2.protocol.Response in project OpenAM by OpenRock.

the class IDPSingleLogout method processLogoutResponse.

/**
     * Gets and processes the Single <code>LogoutResponse</code> from SP,
     * destroys the local session, checks response's issuer
     * and inResponseTo.
     *
     * @param request the HttpServletRequest.
     * @param response the HttpServletResponse.
     * @param samlResponse <code>LogoutResponse</code> in the
     *          XML string format.
     * @param relayState the target URL on successful
     * <code>LogoutResponse</code>.
     * @return true if jsp has sendRedirect for relayState, false otherwise
     * @throws SAML2Exception if error processing
     *          <code>LogoutResponse</code>.
     * @throws SessionException if error processing
     *          <code>LogoutResponse</code>.
     */
public static boolean processLogoutResponse(HttpServletRequest request, HttpServletResponse response, String samlResponse, String relayState) throws SAML2Exception, SessionException {
    String method = "processLogoutResponse : ";
    if (debug.messageEnabled()) {
        debug.message(method + "samlResponse : " + samlResponse);
        debug.message(method + "relayState : " + relayState);
    }
    String rmethod = request.getMethod();
    String binding = SAML2Constants.HTTP_REDIRECT;
    if (rmethod.equals("POST")) {
        binding = SAML2Constants.HTTP_POST;
    }
    String metaAlias = SAML2MetaUtils.getMetaAliasByUri(request.getRequestURI());
    String realm = SAML2Utils.getRealm(SAML2MetaUtils.getRealmByMetaAlias(metaAlias));
    String idpEntityID = sm.getEntityByMetaAlias(metaAlias);
    if (!SAML2Utils.isIDPProfileBindingSupported(realm, idpEntityID, SAML2Constants.SLO_SERVICE, binding)) {
        debug.error("SLO service binding " + binding + " is not supported:" + idpEntityID);
        throw new SAML2Exception(SAML2Utils.bundle.getString("unsupportedBinding"));
    }
    LogoutResponse logoutRes = null;
    if (rmethod.equals("POST")) {
        logoutRes = LogoutUtil.getLogoutResponseFromPost(samlResponse, response);
    } else if (rmethod.equals("GET")) {
        String decodedStr = SAML2Utils.decodeFromRedirect(samlResponse);
        if (decodedStr == null) {
            throw new SAML2Exception(SAML2Utils.bundle.getString("nullDecodedStrFromSamlResponse"));
        }
        logoutRes = ProtocolFactory.getInstance().createLogoutResponse(decodedStr);
    }
    if (logoutRes == null) {
        if (debug.messageEnabled()) {
            debug.message("IDPSingleLogout:processLogoutResponse: logoutRes " + "is null");
        }
        return false;
    }
    String spEntityID = logoutRes.getIssuer().getValue();
    Issuer resIssuer = logoutRes.getIssuer();
    String requestId = logoutRes.getInResponseTo();
    SAML2Utils.verifyResponseIssuer(realm, idpEntityID, resIssuer, requestId);
    boolean needToVerify = SAML2Utils.getWantLogoutResponseSigned(realm, idpEntityID, SAML2Constants.IDP_ROLE);
    if (debug.messageEnabled()) {
        debug.message(method + "metaAlias : " + metaAlias);
        debug.message(method + "realm : " + realm);
        debug.message(method + "idpEntityID : " + idpEntityID);
        debug.message(method + "spEntityID : " + spEntityID);
    }
    if (needToVerify) {
        boolean valid = false;
        if (rmethod.equals("POST")) {
            valid = LogoutUtil.verifySLOResponse(logoutRes, realm, spEntityID, idpEntityID, SAML2Constants.IDP_ROLE);
        } else {
            String queryString = request.getQueryString();
            valid = SAML2Utils.verifyQueryString(queryString, realm, SAML2Constants.IDP_ROLE, spEntityID);
        }
        if (!valid) {
            debug.error("Invalid signature in SLO Response.");
            throw new SAML2Exception(SAML2Utils.bundle.getString("invalidSignInResponse"));
        }
        IDPSSODescriptorElement idpsso = sm.getIDPSSODescriptor(realm, idpEntityID);
        String loc = null;
        if (idpsso != null) {
            List sloList = idpsso.getSingleLogoutService();
            if (sloList != null && !sloList.isEmpty()) {
                loc = LogoutUtil.getSLOResponseServiceLocation(sloList, binding);
                if (loc == null || (loc.length() == 0)) {
                    loc = LogoutUtil.getSLOServiceLocation(sloList, binding);
                }
            }
        }
        if (!SAML2Utils.verifyDestination(logoutRes.getDestination(), loc)) {
            throw new SAML2Exception(SAML2Utils.bundle.getString("invalidDestination"));
        }
    }
    boolean doRelayState = processLogoutResponse(request, response, logoutRes, relayState, metaAlias, idpEntityID, spEntityID, realm, binding);
    // IDPProxy
    Map logoutResponseMap = (Map) IDPCache.logoutResponseCache.get(requestId);
    if ((logoutResponseMap != null) && (!logoutResponseMap.isEmpty())) {
        LogoutResponse logoutResp = (LogoutResponse) logoutResponseMap.get("LogoutResponse");
        String location = (String) logoutResponseMap.get("Location");
        String spEntity = (String) logoutResponseMap.get("spEntityID");
        String idpEntity = (String) logoutResponseMap.get("idpEntityID");
        if (logoutResp != null && location != null && spEntity != null && idpEntity != null) {
            LogoutUtil.sendSLOResponse(response, request, logoutResp, location, relayState, "/", spEntity, SAML2Constants.SP_ROLE, idpEntity, binding);
            return true;
        }
    }
    return doRelayState;
}
Also used : SAML2Exception(com.sun.identity.saml2.common.SAML2Exception) LogoutResponse(com.sun.identity.saml2.protocol.LogoutResponse) Issuer(com.sun.identity.saml2.assertion.Issuer) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map) IDPSSODescriptorElement(com.sun.identity.saml2.jaxb.metadata.IDPSSODescriptorElement)

Example 50 with Response

use of com.sun.identity.saml2.protocol.Response in project OpenAM by OpenRock.

the class IDPSingleLogout method initiateLogoutRequest.

/**
     * Parses the request parameters and initiates the Logout
     * Request to be sent to the SP.
     *
     * @param request the HttpServletRequest.
     * @param response the HttpServletResponse.
     * @param out the print writer for writing out presentation
     * @param binding binding used for this request.
     * @param paramsMap Map of all other parameters.
     *       Following parameters names with their respective
     *       String values are allowed in this paramsMap.
     *       "RelayState" - the target URL on successful Single Logout
     *       "Destination" - A URI Reference indicating the address to
     *                       which the request has been sent.
     *       "Consent" - Specifies a URI a SAML defined identifier
     *                   known as Consent Identifiers.
     *       "Extension" - Specifies a list of Extensions as list of
     *                   String objects.
     * @throws SAML2Exception if error initiating request to SP.
     */
public static void initiateLogoutRequest(HttpServletRequest request, HttpServletResponse response, PrintWriter out, String binding, Map paramsMap) throws SAML2Exception {
    if (debug.messageEnabled()) {
        debug.message("in initiateLogoutRequest");
        debug.message("binding : " + binding);
        debug.message("logoutAll : " + (String) paramsMap.get(SAML2Constants.LOGOUT_ALL));
        debug.message("paramsMap : " + paramsMap);
    }
    boolean logoutall = false;
    String logoutAllValue = (String) paramsMap.get(SAML2Constants.LOGOUT_ALL);
    if ((logoutAllValue != null) && logoutAllValue.equalsIgnoreCase("true")) {
        logoutall = true;
    }
    String metaAlias = (String) paramsMap.get(SAML2Constants.IDP_META_ALIAS);
    try {
        Object session = sessionProvider.getSession(request);
        String sessUser = sessionProvider.getPrincipalName(session);
        if (session == null) {
            throw new SAML2Exception(SAML2Utils.bundle.getString("nullSSOToken"));
        }
        if (metaAlias == null) {
            String[] values = sessionProvider.getProperty(session, SAML2Constants.IDP_META_ALIAS);
            if (values != null && values.length != 0) {
                metaAlias = values[0];
            }
        }
        if (metaAlias == null) {
            throw new SAML2Exception(SAML2Utils.bundle.getString("nullIDPMetaAlias"));
        }
        paramsMap.put(SAML2Constants.METAALIAS, metaAlias);
        String realm = SAML2Utils.getRealm(SAML2MetaUtils.getRealmByMetaAlias(metaAlias));
        String idpEntityID = sm.getEntityByMetaAlias(metaAlias);
        if (idpEntityID == null) {
            debug.error("Identity Provider ID is missing");
            String[] data = { idpEntityID };
            LogUtil.error(Level.INFO, LogUtil.INVALID_IDP, data, null);
            throw new SAML2Exception(SAML2Utils.bundle.getString("nullIDPEntityID"));
        }
        // clean up session index
        String idpSessionIndex = IDPSSOUtil.getSessionIndex(session);
        if (idpSessionIndex == null) {
            if (debug.messageEnabled()) {
                debug.message("No SP session participant(s)");
            }
            MultiProtocolUtils.invalidateSession(session, request, response, SingleLogoutManager.SAML2);
            return;
        }
        // then send the request to the original server
        if (!SAML2FailoverUtils.isSAML2FailoverEnabled() && isMisroutedRequest(request, response, out, session)) {
            return;
        } else {
            if (debug.messageEnabled()) {
                debug.message("IDPSingleLogout.initiateLogoutRequest: " + "SAML2 Failover will be attempted. Be sure SFO is " + "properly configured or the attempt will fail");
            }
        }
        IDPSession idpSession = IDPCache.idpSessionsByIndices.get(idpSessionIndex);
        if (idpSession == null) {
            if (debug.messageEnabled()) {
                debug.message("IDPSLO.initiateLogoutRequest: " + "IDP Session with session index " + idpSessionIndex + " already removed.");
            }
            try {
                if (SAML2FailoverUtils.isSAML2FailoverEnabled()) {
                    SAML2FailoverUtils.deleteSAML2Token(idpSessionIndex);
                }
            } catch (SAML2TokenRepositoryException se) {
                debug.error("IDPSingleLogout.initiateLogoutReq: Error while deleting token from " + "SAML2 Token Repository for idpSessionIndex:" + idpSessionIndex, se);
            }
            IDPCache.authnContextCache.remove(idpSessionIndex);
            MultiProtocolUtils.invalidateSession(session, request, response, SingleLogoutManager.SAML2);
            return;
        }
        if (debug.messageEnabled()) {
            debug.message("idpSessionIndex=" + idpSessionIndex);
        }
        List<NameIDandSPpair> list = idpSession.getNameIDandSPpairs();
        int n = list.size();
        if (debug.messageEnabled()) {
            debug.message("IDPSingleLogout.initiateLogoutReq:" + " NameIDandSPpairs=" + list + ", size=" + n);
        }
        if (n == 0) {
            if (debug.messageEnabled()) {
                debug.message("No SP session participant(s)");
            }
            IDPCache.idpSessionsByIndices.remove(idpSessionIndex);
            if ((agent != null) && agent.isRunning() && (saml2Svc != null)) {
                saml2Svc.setIdpSessionCount((long) IDPCache.idpSessionsByIndices.size());
            }
            try {
                if (SAML2FailoverUtils.isSAML2FailoverEnabled()) {
                    SAML2FailoverUtils.deleteSAML2Token(idpSessionIndex);
                }
            } catch (SAML2TokenRepositoryException se) {
                debug.error("IDPSingleLogout.initiateLogoutReq: Error while deleting token from " + "SAML2 Token Repository for idpSessionIndex:" + idpSessionIndex, se);
            }
            IDPCache.authnContextCache.remove(idpSessionIndex);
            MultiProtocolUtils.invalidateSession(session, request, response, SingleLogoutManager.SAML2);
            return;
        }
        String relayState = (String) paramsMap.get(SAML2Constants.RELAY_STATE);
        // Validate the RelayState URL.
        SAML2Utils.validateRelayStateURL(realm, idpEntityID, relayState, SAML2Constants.IDP_ROLE);
        int soapFailCount = 0;
        idpSession.setOriginatingLogoutRequestBinding(binding);
        for (int i = 0; i < n; i++) {
            NameIDandSPpair pair = list.remove(0);
            removeTransientNameIDFromCache(pair.getNameID());
            String spEntityID = pair.getSPEntityID();
            if (debug.messageEnabled()) {
                debug.message("IDPSingleLogout.initLogoutReq: processing spEntityID " + spEntityID);
            }
            List extensionsList = LogoutUtil.getExtensionsList(paramsMap);
            List<SingleLogoutServiceElement> slosList = getSPSLOServiceEndpoints(realm, spEntityID);
            // get IDP entity config in case of SOAP, for basic auth info
            SPSSOConfigElement spConfig = sm.getSPSSOConfig(realm, spEntityID);
            if (logoutall == true) {
                idpSessionIndex = null;
            }
            SingleLogoutServiceElement logoutEndpoint = LogoutUtil.getMostAppropriateSLOServiceLocation(slosList, idpSession.getOriginatingLogoutRequestBinding());
            if (logoutEndpoint == null) {
                continue;
            }
            StringBuffer requestID = null;
            try {
                requestID = LogoutUtil.doLogout(metaAlias, spEntityID, extensionsList, logoutEndpoint, relayState, idpSessionIndex, pair.getNameID(), request, response, paramsMap, spConfig);
            } catch (SAML2Exception ex) {
                if (logoutEndpoint.getBinding().equals(SAML2Constants.SOAP)) {
                    debug.error("IDPSingleLogout.initiateLogoutRequest:", ex);
                    soapFailCount++;
                    continue;
                } else {
                    throw ex;
                }
            }
            String requestIDStr = requestID.toString();
            String bindingUsed = logoutEndpoint.getBinding();
            if (debug.messageEnabled()) {
                debug.message("\nIDPSLO.requestIDStr = " + requestIDStr + "\nbinding = " + bindingUsed);
            }
            if (!requestIDStr.isEmpty() && (bindingUsed.equals(SAML2Constants.HTTP_REDIRECT) || bindingUsed.equals(SAML2Constants.HTTP_POST))) {
                idpSession.setPendingLogoutRequestID(requestIDStr);
                idpSession.setLogoutAll(logoutall);
                Map logoutMap = (Map) paramsMap.get("LogoutMap");
                if (logoutMap != null && !logoutMap.isEmpty()) {
                    IDPCache.logoutResponseCache.put(requestIDStr, (Map) paramsMap.get("LogoutMap"));
                }
                return;
            }
        }
        //requested binding, or SOAP was used for the logout (or the mixture of this two).
        if (logoutall == true) {
            String userID = sessionProvider.getPrincipalName(idpSession.getSession());
            destroyAllTokenForUser(userID, request, response);
        } else {
            MultiProtocolUtils.invalidateSession(idpSession.getSession(), request, response, SingleLogoutManager.SAML2);
            IDPCache.idpSessionsByIndices.remove(idpSessionIndex);
            if (agent != null && agent.isRunning() && saml2Svc != null) {
                saml2Svc.setIdpSessionCount((long) IDPCache.idpSessionsByIndices.size());
            }
            IDPCache.authnContextCache.remove(idpSessionIndex);
        }
        //handling the case when the auth was initiated with HTTP-Redirect, but only SOAP or no SLO endpoint was
        //available, and also the case when the whole logout process was using SOAP binding from the beginning
        int logoutStatus = SingleLogoutManager.LOGOUT_SUCCEEDED_STATUS;
        boolean isMultiProtocol = MultiProtocolUtils.isMultipleProtocolSession(request, SingleLogoutManager.SAML2);
        //TODO: would be nice to actually return the correct message in idpSingleLogoutInit.jsp
        if (soapFailCount == n) {
            if (isMultiProtocol) {
                logoutStatus = SingleLogoutManager.LOGOUT_FAILED_STATUS;
            }
        } else if (soapFailCount > 0) {
            if (isMultiProtocol) {
                logoutStatus = SingleLogoutManager.LOGOUT_PARTIAL_STATUS;
            }
        }
        // processing multi-federation protocol session
        if (isMultiProtocol) {
            Set set = new HashSet();
            set.add(session);
            boolean isSOAPInitiated = binding.equals(SAML2Constants.SOAP) ? true : false;
            int retStat = SingleLogoutManager.LOGOUT_SUCCEEDED_STATUS;
            try {
                debug.message("IDPSingleLogout.initLogReq: MP");
                retStat = SingleLogoutManager.getInstance().doIDPSingleLogout(set, sessUser, request, response, isSOAPInitiated, true, SingleLogoutManager.SAML2, realm, idpEntityID, null, relayState, null, null, logoutStatus);
            } catch (Exception ex) {
                debug.warning("IDPSingleLogout.initiateLoogutReq: MP", ex);
                throw new SAML2Exception(ex.getMessage());
            }
            if (debug.messageEnabled()) {
                debug.message("IDPSingleLogout.initLogoutRequest: " + "SLOManager return status = " + retStat);
            }
            switch(retStat) {
                case SingleLogoutManager.LOGOUT_FAILED_STATUS:
                    throw new SAML2Exception(SAML2Utils.bundle.getString("sloFailed"));
                case SingleLogoutManager.LOGOUT_PARTIAL_STATUS:
                    throw new SAML2Exception(SAML2Utils.bundle.getString("partialLogout"));
                default:
                    break;
            }
        }
    } catch (SAML2MetaException sme) {
        debug.error("Error retreiving metadata", sme);
        throw new SAML2Exception(SAML2Utils.bundle.getString("metaDataError"));
    } catch (SessionException ssoe) {
        debug.error("SessionException: ", ssoe);
        throw new SAML2Exception(SAML2Utils.bundle.getString("metaDataError"));
    }
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) SPSSOConfigElement(com.sun.identity.saml2.jaxb.entityconfig.SPSSOConfigElement) SessionException(com.sun.identity.plugin.session.SessionException) SessionException(com.sun.identity.plugin.session.SessionException) SAML2MetaException(com.sun.identity.saml2.meta.SAML2MetaException) SAML2TokenRepositoryException(org.forgerock.openam.federation.saml2.SAML2TokenRepositoryException) IOException(java.io.IOException) SAML2Exception(com.sun.identity.saml2.common.SAML2Exception) SAML2Exception(com.sun.identity.saml2.common.SAML2Exception) SingleLogoutServiceElement(com.sun.identity.saml2.jaxb.metadata.SingleLogoutServiceElement) SAML2TokenRepositoryException(org.forgerock.openam.federation.saml2.SAML2TokenRepositoryException) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map) SAML2MetaException(com.sun.identity.saml2.meta.SAML2MetaException) HashSet(java.util.HashSet)

Aggregations

SAML2Exception (com.sun.identity.saml2.common.SAML2Exception)119 List (java.util.List)53 SAML2MetaException (com.sun.identity.saml2.meta.SAML2MetaException)45 ArrayList (java.util.ArrayList)41 IOException (java.io.IOException)40 SessionException (com.sun.identity.plugin.session.SessionException)35 Response (com.sun.identity.saml2.protocol.Response)31 SOAPException (javax.xml.soap.SOAPException)31 Issuer (com.sun.identity.saml2.assertion.Issuer)28 HttpServletResponse (javax.servlet.http.HttpServletResponse)28 SAML2TokenRepositoryException (org.forgerock.openam.federation.saml2.SAML2TokenRepositoryException)25 Map (java.util.Map)24 Assertion (com.sun.identity.saml2.assertion.Assertion)23 SPSSODescriptorElement (com.sun.identity.saml2.jaxb.metadata.SPSSODescriptorElement)23 SOAPMessage (javax.xml.soap.SOAPMessage)22 IDPSSODescriptorElement (com.sun.identity.saml2.jaxb.metadata.IDPSSODescriptorElement)20 Date (java.util.Date)20 HashMap (java.util.HashMap)20 Element (org.w3c.dom.Element)20 X509Certificate (java.security.cert.X509Certificate)16