com.vmware.identity.proxyservice.LogoutProcessorImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.vmware.identity.proxyservice.LogoutProcessorImpl.java

Source

/*
 *  Copyright (c) 2012-2015 VMware, Inc.  All Rights Reserved.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not
 *  use this file except in compliance with the License.  You may obtain a copy
 *  of the License at http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, without
 *  warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED.  See the
 *  License for the specific language governing permissions and limitations
 *  under the License.
 */

package com.vmware.identity.proxyservice;

import java.io.IOException;
import java.util.Collection;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.Validate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;

import com.vmware.identity.diagnostics.DiagnosticsLoggerFactory;
import com.vmware.identity.diagnostics.IDiagnosticsLogger;
import com.vmware.identity.samlservice.LogoutState;
import com.vmware.identity.samlservice.OasisNames;
import com.vmware.identity.samlservice.LogoutState.ProcessingState;
import com.vmware.identity.samlservice.SamlValidator.ValidationResult;
import com.vmware.identity.samlservice.impl.SamlServiceImpl;
import com.vmware.identity.session.Session;
import com.vmware.identity.session.SessionManager;
import com.vmware.identity.websso.client.LogoutProcessor;
import com.vmware.identity.websso.client.Message;

/**
 * Proxying service Logout Processor Implementation
 *
 */
public class LogoutProcessorImpl implements LogoutProcessor {

    @Autowired
    private MessageSource messageSource;

    @Autowired
    private SessionManager sessionManager;

    private static final IDiagnosticsLogger logger = DiagnosticsLoggerFactory.getLogger(LogoutProcessorImpl.class);
    private LogoutState logoutState;

    /**
     * Error callback in processing logout response or request from external IDP.
     * @see com.vmware.identity.websso.client.LogoutProcessor#logoutError(com.vmware.identity.websso.client.Message, javax.servlet.http.HttpServletResponse)
     */
    @Override
    public void logoutError(Message arg0, HttpServletRequest request, HttpServletResponse response) {
        Validate.notNull(arg0, "Message");

        com.vmware.identity.websso.client.ValidationResult clientVr = arg0.getValidationResult();
        ValidationResult vr = null;

        String message;

        //The error could be from external idp or from validation of response from external idp
        if (arg0.getStatus() != null && !arg0.getStatus().equals(OasisNames.SUCCESS)) {
            //If it is external IDP authentication error.
            vr = new ValidationResult(HttpServletResponse.SC_BAD_REQUEST, arg0.getStatus(), arg0.getSubstatus());
            message = vr.getMessage(messageSource, getLogoutState().getLocale());
            logger.error("Error logout message from Externel IDP: {} message: {}", vr.getResponseCode(), message);

        } else {
            //Else send the validation error to RP
            vr = new ValidationResult(clientVr.getResponseCode(), clientVr.getStatus(), clientVr.getSubstatus());
            message = vr.getMessage(messageSource, getLogoutState().getLocale());
            logger.error("Failed in validating logout response from Externel IDP: {} message: {}",
                    vr.getResponseCode(), message);
        }

        try {
            response.sendError(vr.getResponseCode(), message);
        } catch (IOException e) {
            logger.error("Caught IOException in sending error to logout request/response issurer");
        }
    }

    /**
     * Callback function at receiving a logout request from the trusted IDP.
     * This function will find corresponding lotus login session, send a slo
     *  request to each of the session participants.
     *  The client library sloconstroller will respond to slo requester when
     *   get back from this function.
     *
    * @param message
    *             Websso message
    * @param request
    * @param response
    */
    @Override
    public void logoutRequest(Message arg0, HttpServletRequest request, HttpServletResponse response,
            String tenant) {
        Validate.notEmpty(tenant);
        //TODO.  This is used only for lotus joining extern IDP federation (with more than one SP).  Saas used case.
        // incoming logout request from the IDP, need to clean up session info on the server
        //

        //1 create a new RequestState
        LogoutState loState = new LogoutState(request, response, sessionManager, null, null);

        //2 setup validation state since this is already validated by client lib
        ValidationResult vr = new ValidationResult(arg0.getValidationResult().getResponseCode(), arg0.getStatus(),
                arg0.getSubstatus());
        loState.setValidationResult(vr);
        //3 set to logout processor
        this.setLogoutState(loState);
        this.getLogoutState().setProcessingState(ProcessingState.PARSED);
        loState.getIdmAccessor().setTenant(tenant);

        //4 Find lotus session id using ext IDP session id. Remove castle session cookie.
        Session lotusSession = findSessionIdByExtSessionId(arg0.getSessionIndex());
        if (lotusSession == null) {
            //Ignore the request and log a warning.
            logger.warn("No session found matching external session: {}", arg0.getSessionIndex());
            return;
        }
        //Now, we found the lotus session. Get loState populated with session related infor.
        loState.setSessionId(lotusSession.getId());
        loState.setIssuerValue(lotusSession.getExtIDPUsed().getEntityID());
        loState.removeResponseHeaders();

        //5 Send SLO request to each of the session participants.
        try {
            SamlServiceImpl.sendSLORequestsToOtherParticipants(tenant, loState);
        } catch (IOException e) {
            logger.error("Caught IOException in sending logout request to service providers.");
        }
    }

    /**
     *
    * @param sessionIndex
    *             Websso message
    * @return null or websso session string
     */
    private Session findSessionIdByExtSessionId(String extSessionIndex) {
        Validate.notNull(extSessionIndex, "extSessionIndex");
        Validate.notNull(logoutState, "logoutState");

        SessionManager sessionManager = logoutState.getSessionManager();

        Validate.notNull(sessionManager, "sessionManager");
        Collection<Session> sessions = sessionManager.getAll();

        Validate.notEmpty(sessions, "sessions");

        Session localSessionToLogout = null;

        for (Session localSession : sessions) {
            if (localSession.getExtIDPSessionID().equals(extSessionIndex))
                localSessionToLogout = localSession;
            else {
                logger.debug("Session matching hit miss: session= {}", localSession.toString());
            }
        }

        if (localSessionToLogout != null) {
            logger.debug("Found a session requested in external IDP SLO request {}",
                    localSessionToLogout.toString());
            return localSessionToLogout;
        }
        return null;
    }

    /**
      * Callback function at receiving a validated successful logout response from trusted IDP.
     * It send logout success response to the service that initiated the SLO request. And logout requests
     * to other participants.
     *
     * @param message
     *             Websso message
     * @param request
     * @param response
      */
    @Override
    public void logoutSuccess(Message arg0, HttpServletRequest request, HttpServletResponse response) {

        String tenant = logoutState.getIdmAccessor().getTenant();

        //Send logout request to other participating SP's
        try {
            if (logoutState.needLogoutRequest()) {
                //send slo request to all non-initiating relying parties
                SamlServiceImpl.sendSLORequestsToOtherParticipants(tenant, logoutState);
            }
        } catch (IOException e) {
            logger.error("Catch IOException in sending logout requests to other service providers.");
        }

        //Send logout response to other initiating SP
        try {
            if (logoutState.needLogoutResponse()) {
                String redirectUrl = SamlServiceImpl.buildResponseUrl(tenant, logoutState);

                logger.info("Sending SAML logout response to SP. Redirect url is: {} ", redirectUrl);

                if (redirectUrl != null) {
                    response.sendRedirect(redirectUrl);
                } else {
                    SamlServiceImpl.sendLogoutError(logoutState.getLocale(), response, logoutState, messageSource);
                }
            }
        } catch (IOException e) {
            logger.error("Caught IOException in sending logout response to service provider.");
        }
    }

    /* (non-Javadoc)
     * @see com.vmware.identity.websso.client.LogoutProcessor#internalError(java.lang.Exception, javax.servlet.http.HttpServletRequest)
     */
    @Override
    public void internalError(Exception internalError, HttpServletRequest request, HttpServletResponse response) {
        logger.error("internalError() is called in processing logout request/response from "
                + "external IDP. This means the request or response is understood and validated. "
                + "But responder can send the response or request to the IDP because of unexpected error.");

        try {
            LogoutState logoutState = getLogoutState();
            if (logoutState != null) {
                //Logout request was initiated by one of SP register to this instance.
                //Send error response to the initiating SP

                String message = getLogoutState().getMessageSource().getMessage("BadRequest", null,
                        getLogoutState().getLocale());

                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
            }
        } catch (IOException e) {
            logger.error("Caught IOException in sending processing error to service provider");
        }

    }

    public void setLogoutState(LogoutState t) {
        this.logoutState = t;
    }

    public LogoutState getLogoutState() {
        return logoutState;
    }

}