// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.cloud.api;

import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.URLDecoder;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.Set;

import javax.inject.Inject;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.cloudstack.api.APICommand;
import com.cloud.api.auth.DefaultForgotPasswordAPIAuthenticatorCmd;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.ApiServerService;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.auth.APIAuthenticationManager;
import org.apache.cloudstack.api.auth.APIAuthenticationType;
import org.apache.cloudstack.api.auth.APIAuthenticator;
import org.apache.cloudstack.api.command.user.consoleproxy.CreateConsoleEndpointCmd;
import org.apache.cloudstack.api.command.user.gui.theme.ListGuiThemesCmd;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.managed.context.ManagedContext;
import org.apache.cloudstack.utils.consoleproxy.ConsoleAccessUtils;
import org.apache.commons.collections.MapUtils;

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.commons.lang3.EnumUtils;
import org.jetbrains.annotations.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;

import com.cloud.api.auth.ListUserTwoFactorAuthenticatorProvidersCmd;
import com.cloud.api.auth.SetupUserTwoFactorAuthenticationCmd;
import com.cloud.api.auth.ValidateUserTwoFactorAuthenticationCodeCmd;
import com.cloud.projects.Project;
import com.cloud.projects.dao.ProjectDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManagerImpl;
import com.cloud.user.AccountService;
import com.cloud.user.User;
import com.cloud.user.UserAccount;

import com.cloud.utils.HttpUtils;
import com.cloud.utils.HttpUtils.ApiSessionKeySameSite;
import com.cloud.utils.HttpUtils.ApiSessionKeyCheckOption;
import com.cloud.utils.StringUtils;
import com.cloud.utils.db.EntityManager;
import com.cloud.utils.net.NetUtils;

@Component("apiServlet")
public class ApiServlet extends HttpServlet {
    protected static Logger LOGGER = LogManager.getLogger(ApiServlet.class);
    private static final Logger ACCESSLOGGER = LogManager.getLogger("apiserver." + ApiServlet.class.getName());
    private static final String REPLACEMENT = "_";
    private static final String LOGGER_REPLACEMENTS = "[\n\r\t]";
    private static final Pattern GET_REQUEST_COMMANDS = Pattern.compile("^(get|list|query|find)(\\w+)+$");
    private static final HashSet<String> GET_REQUEST_COMMANDS_LIST = new HashSet<>(Set.of("isaccountallowedtocreateofferingswithtags",
            "readyforshutdown", "cloudianisenabled", "quotabalance", "quotasummary", "quotatarifflist", "quotaisenabled", "quotastatement", "verifyoauthcodeandgetuser"));
    private static final HashSet<String> POST_REQUESTS_TO_DISABLE_LOGGING = new HashSet<>(Set.of(
            "login",
            "oauthlogin",
            "createaccount",
            "createuser",
            "updateuser",
            "forgotpassword",
            "resetpassword",
            "importrole",
            "updaterolepermission",
            "updateprojectrolepermission",
            "createstoragepool",
            "addhost",
            "updatehostpassword",
            "addcluster",
            "addvmwaredc",
            "configureoutofbandmanagement",
            "uploadcustomcertificate",
            "addciscovnmcresource",
            "addnetscalerloadbalancer",
            "createtungstenfabricprovider",
            "addnsxcontroller",
            "configtungstenfabricservice",
            "createnetworkacl",
            "updatenetworkaclitem",
            "quotavalidateactivationrule",
            "quotatariffupdate",
            "listandswitchsamlaccount",
            "uploadresourceicon"
    ));

    @Inject
    ApiServerService apiServer;
    @Inject
    AccountService accountMgr;
    @Inject
    EntityManager entityMgr;
    @Inject
    ManagedContext managedContext;
    @Inject
    APIAuthenticationManager authManager;
    @Inject
    private ProjectDao projectDao;

    public ApiServlet() {
    }

    @Override
    public void init(final ServletConfig config) throws ServletException {
        SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext());
    }

    @Override
    protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) {
        processRequest(req, resp);
    }

    @Override
    protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) {
        processRequest(req, resp);
    }

    /**
     * For HTTP GET requests, it seems that HttpServletRequest.getParameterMap() actually tries
     * to unwrap URL encoded content from ISO-9959-1.
     * After failed in using setCharacterEncoding() to control it, end up with following hacking:
     * for all GET requests, we will override it with our-own way of UTF-8 based URL decoding.
     * @param req request containing parameters
     * @param params output of "our" map of parameters/values
     */
    void utf8Fixup(final HttpServletRequest req, final Map<String, Object[]> params) {
        if (req.getQueryString() == null) {
            return;
        }

        final String[] paramsInQueryString = req.getQueryString().split("&");
        if (paramsInQueryString != null) {
            for (final String param : paramsInQueryString) {
                final String[] paramTokens = param.split("=", 2);
                if (paramTokens.length == 2) {
                    String name = decodeUtf8(paramTokens[0]);
                    String value = decodeUtf8(paramTokens[1]);
                    params.put(name, new String[] {value});
                } else {
                    LOGGER.debug("Invalid parameter in URL found. param: " + param);
                }
            }
        }
    }

    private String decodeUtf8(final String value) {
        try {
            return URLDecoder.decode(value, "UTF-8");
        } catch (final UnsupportedEncodingException e) {
            //should never happen
            return null;
        }
    }

    private void processRequest(final HttpServletRequest req, final HttpServletResponse resp) {
        managedContext.runWithContext(new Runnable() {
            @Override
            public void run() {
                processRequestInContext(req, resp);
            }
        });
    }

    private void checkSingleQueryParameterValue(Map<String, String[]> params) {
        params.forEach((k, v) -> {
            if (v.length > 1) {
                String message = String.format("Query parameter '%s' has multiple values %s. Only the last value will be respected." +
                    "It is advised to pass only a single parameter", k, Arrays.toString(v));
                LOGGER.warn(message);
            }
        });
    }

    void processRequestInContext(final HttpServletRequest req, final HttpServletResponse resp) {
        InetAddress remoteAddress = null;
        try {
            remoteAddress = getClientAddress(req);
        } catch (UnknownHostException e) {
            LOGGER.warn("UnknownHostException when trying to lookup remote IP-Address. This should never happen. Blocking request.", e);
            final String response = apiServer.getSerializedApiError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                    "UnknownHostException when trying to lookup remote IP-Address", null,
                    HttpUtils.RESPONSE_TYPE_XML);
            HttpUtils.writeHttpResponse(resp, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                    HttpUtils.RESPONSE_TYPE_XML, ApiServer.JSONContentType.value());
            return;
        }

        final StringBuilder auditTrailSb = new StringBuilder(128);
        auditTrailSb.append(" ").append(remoteAddress.getHostAddress());
        auditTrailSb.append(" -- ").append(req.getMethod()).append(' ');
        // get the response format since we'll need it in a couple of places
        String responseType = HttpUtils.RESPONSE_TYPE_XML;
        final Map<String, Object[]> params = new HashMap<String, Object[]>();
        Map<String, String[]> reqParams = req.getParameterMap();
        checkSingleQueryParameterValue(reqParams);
        params.putAll(reqParams);

        utf8Fixup(req, params);

        final Object[] commandObj = params.get(ApiConstants.COMMAND);
        final String command = commandObj == null ? null : (String) commandObj[0];

        // logging the request start and end in management log for easy debugging
        String reqStr = "";
        String cleanQueryString = StringUtils.cleanString(req.getQueryString());
        if (LOGGER.isDebugEnabled()) {
            reqStr = auditTrailSb.toString() + " " + cleanQueryString;
            if (req.getMethod().equalsIgnoreCase("POST") && org.apache.commons.lang3.StringUtils.isNotBlank(command)) {
                if (!POST_REQUESTS_TO_DISABLE_LOGGING.contains(command.toLowerCase()) && !reqParams.containsKey(ApiConstants.USER_DATA)) {
                    String cleanParamsString = getCleanParamsString(reqParams);
                    if (org.apache.commons.lang3.StringUtils.isNotBlank(cleanParamsString)) {
                        reqStr += "\n" + cleanParamsString;
                    }
                } else {
                    reqStr += " " + command;
                }
            }
            LOGGER.debug("===START=== " + reqStr);
        }

        try {
            resp.setContentType(HttpUtils.XML_CONTENT_TYPE);

            HttpSession session = req.getSession(false);
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace(String.format("session found: %s", session));
            }
            final Object[] responseTypeParam = params.get(ApiConstants.RESPONSE);
            if (responseTypeParam != null) {
                responseType = (String)responseTypeParam[0];
            }

            final Object[] userObj = params.get(ApiConstants.USERNAME);
            String username = userObj == null ? null : (String)userObj[0];
            if (LOGGER.isTraceEnabled()) {
                String logCommand = saveLogString(command);
                String logName = saveLogString(username);
                LOGGER.trace(String.format("command %s processing for user \"%s\"",
                        logCommand,
                        logName));
            }

            if (command != null && !command.equals(ValidateUserTwoFactorAuthenticationCodeCmd.APINAME)) {
                APIAuthenticator apiAuthenticator = authManager.getAPIAuthenticator(command);
                if (apiAuthenticator != null) {
                    auditTrailSb.append("command=");
                    auditTrailSb.append(command);

                    int httpResponseCode = HttpServletResponse.SC_OK;
                    String responseString = null;

                    if (apiAuthenticator.getAPIType() == APIAuthenticationType.LOGIN_API) {
                        if (session != null) {
                            invalidateHttpSession(session, "invalidating session for login call");
                        }
                        session = req.getSession(true);

                        if (ApiServer.EnableSecureSessionCookie.value()) {
                            resp.setHeader("SET-COOKIE", String.format("JSESSIONID=%s;Secure;HttpOnly;Path=/client", session.getId()));
                            if (LOGGER.isDebugEnabled()) {
                                LOGGER.debug("Session cookie is marked secure!");
                            }
                        }
                    }

                    try {
                        if (LOGGER.isTraceEnabled()) {
                            LOGGER.trace(String.format("apiAuthenticator.authenticate(%s, params[%d], %s, %s, %s, %s, %s,%s)",
                                    saveLogString(command), params.size(), session.getId(), remoteAddress.getHostAddress(), saveLogString(responseType), "auditTrailSb", "req", "resp"));
                        }
                        responseString = apiAuthenticator.authenticate(command, params, session, remoteAddress, responseType, auditTrailSb, req, resp);
                        if (session != null && session.getAttribute(ApiConstants.SESSIONKEY) != null) {
                            String sameSite = getApiSessionKeySameSite();
                            resp.addHeader("SET-COOKIE", String.format("%s=%s;HttpOnly;%s", ApiConstants.SESSIONKEY, session.getAttribute(ApiConstants.SESSIONKEY), sameSite));
                        }
                    } catch (ServerApiException e) {
                        httpResponseCode = e.getErrorCode().getHttpCode();
                        responseString = e.getMessage();
                        if (!DefaultForgotPasswordAPIAuthenticatorCmd.APINAME.equalsIgnoreCase(command) || StringUtils.isNotBlank(username)) {
                            LOGGER.debug("Authentication failure: {}", e.getMessage());
                        }
                    }

                    if (apiAuthenticator.getAPIType() == APIAuthenticationType.LOGOUT_API) {
                        if (session == null) {
                            throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Session not found for the logout process.");
                        }

                        final Long userId = (Long) session.getAttribute("userid");
                        final Account account = (Account) session.getAttribute("accountobj");
                        Long accountId = null;
                        if (account != null) {
                            accountId = account.getId();
                        }
                        auditTrailSb.insert(0, "(userId=" + userId + " accountId=" + accountId + " sessionId=" + session.getId() + ")");
                        if (userId != null) {
                            apiServer.logoutUser(userId);
                        }
                        invalidateHttpSession(session, "invalidating session after logout call");
                        clearRequestCookies(req, resp);
                    }
                    HttpUtils.writeHttpResponse(resp, responseString, httpResponseCode, responseType, ApiServer.JSONContentType.value());
                    return;
                }
            } else {
                LOGGER.trace("no command available");
            }
            auditTrailSb.append(cleanQueryString);
            final boolean isNew = ((session == null) ? true : session.isNew());

            // Initialize an empty context and we will update it after we have verified the request below,
            // we no longer rely on web-session here, verifyRequest will populate user/account information
            // if a API key exists

            if (isNew && LOGGER.isTraceEnabled()) {
                LOGGER.trace(String.format("new session: %s", session));
            }

            if (!isNew && (command.equalsIgnoreCase(ValidateUserTwoFactorAuthenticationCodeCmd.APINAME) || (!skip2FAcheckForAPIs(command) && !skip2FAcheckForUser(session)))) {
                LOGGER.debug("Verifying two factor authentication");
                boolean success = verify2FA(session, command, auditTrailSb, params, remoteAddress, responseType, req, resp);
                if (!success) {
                    LOGGER.debug("Verification of two factor authentication failed");
                    return;
                }
            }

            if (apiServer.isPostRequestsAndTimestampsEnforced() && !isStateChangingCommandUsingPOST(command, req.getMethod(), params)) {
                String errorText = String.format("State changing command %s needs to be sent using POST request", command);
                if (command.equalsIgnoreCase("updateConfiguration") && params.containsKey("name")) {
                    errorText = String.format("Changes for configuration %s needs to be sent using POST request", params.get("name")[0]);
                }
                auditTrailSb.append(" " + HttpServletResponse.SC_BAD_REQUEST + " " + errorText);
                final String serializedResponse =
                        apiServer.getSerializedApiError(new ServerApiException(ApiErrorCode.BAD_REQUEST, errorText), params,
                                responseType);
                HttpUtils.writeHttpResponse(resp, serializedResponse, HttpServletResponse.SC_BAD_REQUEST, responseType, ApiServer.JSONContentType.value());
                return;
            }

            Long userId = null;
            if (!isNew) {
                userId = (Long)session.getAttribute("userid");
                final String account = (String) session.getAttribute("account");
                final Object accountObj = session.getAttribute("accountobj");
                if (account != null) {
                    if (invalidateHttpSessionIfNeeded(req, resp, auditTrailSb, responseType, params, session, account)) return;
                } else {
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("no account, this request will be validated through apikey(%s)/signature");
                    }
                }

                if (!requestChecksoutAsSane(resp, auditTrailSb, responseType, params, session, command, userId, account, accountObj))
                    return;
            } else {
                CallContext.register(accountMgr.getSystemUser(), accountMgr.getSystemAccount());
            }
            setProjectContext(params);
            setGuiThemeParameterIfApiCallIsUnauthenticated(userId, command, req, params);

            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace(String.format("verifying request for user %s from %s with %d parameters",
                        userId, remoteAddress.getHostAddress(), params.size()));
            }
            if (apiServer.verifyRequest(params, userId, remoteAddress)) {
                auditTrailSb.insert(0, "(userId=" + CallContext.current().getCallingUserId() + " accountId=" + CallContext.current().getCallingAccount().getId() +
                        " sessionId=" + (session != null ? session.getId() : null) + ")");

                // Add the HTTP method (GET/POST/PUT/DELETE) as well into the params map.
                params.put("httpmethod", new String[]{req.getMethod()});
                setProjectContext(params);
                setClientAddressForConsoleEndpointAccess(command, params, req);
                final String response = apiServer.handleRequest(params, responseType, auditTrailSb);
                HttpUtils.writeHttpResponse(resp, response != null ? response : "", HttpServletResponse.SC_OK, responseType, ApiServer.JSONContentType.value());
            } else {
                if (session != null) {
                    invalidateHttpSession(session, String.format("request verification failed for %s from %s", userId, remoteAddress.getHostAddress()));
                }

                auditTrailSb.append(" " + HttpServletResponse.SC_UNAUTHORIZED + " " + "unable to verify user credentials and/or request signature");
                final String serializedResponse =
                        apiServer.getSerializedApiError(HttpServletResponse.SC_UNAUTHORIZED, "unable to verify user credentials and/or request signature", params,
                                responseType);
                HttpUtils.writeHttpResponse(resp, serializedResponse, HttpServletResponse.SC_UNAUTHORIZED, responseType, ApiServer.JSONContentType.value());
            }
        } catch (final ServerApiException se) {
            final String serializedResponseText = apiServer.getSerializedApiError(se, params, responseType);
            resp.setHeader("X-Description", se.getDescription());
            HttpUtils.writeHttpResponse(resp, serializedResponseText, se.getErrorCode().getHttpCode(), responseType, ApiServer.JSONContentType.value());
            auditTrailSb.append(" " + se.getErrorCode() + " " + se.getDescription());
        } catch (final Exception ex) {
            LOGGER.error("unknown exception writing api response", ex);
            auditTrailSb.append(" unknown exception writing api response");
        } finally {
            ACCESSLOGGER.info(auditTrailSb.toString());
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("===END=== " + reqStr);
            }
            // cleanup user context to prevent from being peeked in other request context
            CallContext.unregister();
        }
    }

    public static String getApiSessionKeySameSite() {
        ApiSessionKeySameSite sameSite = EnumUtils.getEnumIgnoreCase(ApiSessionKeySameSite.class,
                ApiServer.ApiSessionKeyCookieSameSiteSetting.value(), ApiSessionKeySameSite.Lax);
        switch (sameSite) {
            case Strict:
                return "SameSite=Strict";
            case NoneAndSecure:
                return "SameSite=None;Secure";
            case Null:
                return "";
            case Lax:
            default:
                return "SameSite=Lax";
        }
    }

    private void setGuiThemeParameterIfApiCallIsUnauthenticated(Long userId, String command, HttpServletRequest req, Map<String, Object[]> params) {
        String listGuiThemesApiName = ListGuiThemesCmd.class.getAnnotation(APICommand.class).name();

        if (userId != null || !listGuiThemesApiName.equalsIgnoreCase(command)) {
            return;
        }

        String serverName = req.getServerName();
        LOGGER.info("Unauthenticated call to {} API, thus, the `commonName` parameter will be inferred as {}.", listGuiThemesApiName, serverName);
        params.put(ApiConstants.COMMON_NAME, new String[]{serverName});
    }


    private boolean checkIfAuthenticatorIsOf2FA(String command) {
        boolean verify2FA = false;
        APIAuthenticator apiAuthenticator = authManager.getAPIAuthenticator(command);
        if (apiAuthenticator != null && apiAuthenticator.getAPIType().equals(APIAuthenticationType.LOGIN_2FA_API)) {
            verify2FA = true;
        } else {
            verify2FA = false;
        }
        return verify2FA;
    }

    private boolean isStateChangingCommandUsingPOST(String command, String method, Map<String, Object[]> params) {
        if (command == null || (!GET_REQUEST_COMMANDS.matcher(command.toLowerCase()).matches() && !GET_REQUEST_COMMANDS_LIST.contains(command.toLowerCase())
                && !command.equalsIgnoreCase("updateConfiguration") && !method.equals("POST"))) {
            return false;
        }
        return !command.equalsIgnoreCase("updateConfiguration") || method.equals("POST") || (params.containsKey("name")
                && params.get("name")[0].toString().equalsIgnoreCase(ApiServer.EnforcePostRequestsAndTimestamps.key()));
    }

    protected boolean skip2FAcheckForAPIs(String command) {
        boolean skip2FAcheck = false;

        if (command.equalsIgnoreCase(ApiConstants.LIST_IDPS)
                || command.equalsIgnoreCase(ApiConstants.LIST_APIS)
                || command.equalsIgnoreCase(ListUserTwoFactorAuthenticatorProvidersCmd.APINAME)
                || command.equalsIgnoreCase(SetupUserTwoFactorAuthenticationCmd.APINAME)) {
            skip2FAcheck = true;
        }
        return skip2FAcheck;
    }

    protected boolean skip2FAcheckForUser(HttpSession session) {
        boolean skip2FAcheck = false;
        Long userId = (Long) session.getAttribute("userid");
        boolean is2FAverified = (boolean) session.getAttribute(ApiConstants.IS_2FA_VERIFIED);
        if (is2FAverified) {
            LOGGER.debug(String.format("Two factor authentication is already verified for the user %d, so skipping", userId));
            skip2FAcheck = true;
        } else {
            UserAccount userAccount = accountMgr.getUserAccountById(userId);
            boolean is2FAenabled = userAccount.isUser2faEnabled();
            if (is2FAenabled) {
                skip2FAcheck = false;
            } else {
                Long domainId = userAccount.getDomainId();
                boolean is2FAmandated = Boolean.TRUE.equals(AccountManagerImpl.enableUserTwoFactorAuthentication.valueIn(domainId)) && Boolean.TRUE.equals(AccountManagerImpl.mandateUserTwoFactorAuthentication.valueIn(domainId));
                if (is2FAmandated) {
                    skip2FAcheck = false;
                } else {
                    skip2FAcheck = true;
                }
            }
        }
        return skip2FAcheck;
    }

    protected boolean verify2FA(HttpSession session, String command, StringBuilder auditTrailSb, Map<String, Object[]> params,
                                InetAddress remoteAddress, String responseType, HttpServletRequest req, HttpServletResponse resp) {
        boolean verify2FA = false;
        if (command.equals(ValidateUserTwoFactorAuthenticationCodeCmd.APINAME)) {
            APIAuthenticator apiAuthenticator = authManager.getAPIAuthenticator(command);
            if (apiAuthenticator != null) {
                String responseString = apiAuthenticator.authenticate(command, params, session, remoteAddress, responseType, auditTrailSb, req, resp);
                session.setAttribute(ApiConstants.IS_2FA_VERIFIED, true);
                HttpUtils.writeHttpResponse(resp, responseString, HttpServletResponse.SC_OK, responseType, ApiServer.JSONContentType.value());
                verify2FA = true;
            } else {
                LOGGER.error("Cannot find API authenticator while verifying 2FA");
                auditTrailSb.append(" Cannot find API authenticator while verifying 2FA");
                verify2FA = false;
            }
        } else {
            // invalidate the session
            Long userId = (Long) session.getAttribute("userid");
            UserAccount userAccount = accountMgr.getUserAccountById(userId);
            boolean is2FAenabled = userAccount.isUser2faEnabled();
            String keyFor2fa = userAccount.getKeyFor2fa();
            String providerFor2fa = userAccount.getUser2faProvider();
            String errorMsg;
            if (is2FAenabled) {
                if (org.apache.commons.lang3.StringUtils.isEmpty(keyFor2fa) || org.apache.commons.lang3.StringUtils.isEmpty(providerFor2fa)) {
                    errorMsg = "Two factor authentication is mandated by admin, user needs to setup 2FA using setupUserTwoFactorAuthentication API and" +
                            " then verify 2FA using validateUserTwoFactorAuthenticationCode API before calling other APIs. Existing session is invalidated.";
                } else {
                    errorMsg = "Two factor authentication 2FA is enabled but not verified, please verify 2FA using validateUserTwoFactorAuthenticationCode API before calling other APIs. Existing session is invalidated.";
                }
            } else {
                // when (is2FAmandated) is true
                errorMsg = "Two factor authentication is mandated by admin, user needs to setup 2FA using setupUserTwoFactorAuthentication API and" +
                        " then verify 2FA using validateUserTwoFactorAuthenticationCode API before calling other APIs. Existing session is invalidated.";
            }
            LOGGER.error(errorMsg);

            invalidateHttpSession(session, String.format("Unable to process the API request for %s from %s due to %s", userId, remoteAddress.getHostAddress(), errorMsg));
            auditTrailSb.append(" " + ApiErrorCode.UNAUTHORIZED2FA + " " + errorMsg);
            final String serializedResponse = apiServer.getSerializedApiError(ApiErrorCode.UNAUTHORIZED2FA.getHttpCode(), "Unable to process the API request due to :" + errorMsg, params, responseType);
            HttpUtils.writeHttpResponse(resp, serializedResponse, ApiErrorCode.UNAUTHORIZED2FA.getHttpCode(), responseType, ApiServer.JSONContentType.value());
            verify2FA = false;
        }

        return verify2FA;
    }
    protected void setClientAddressForConsoleEndpointAccess(String command, Map<String, Object[]> params, HttpServletRequest req) throws UnknownHostException {
        if (org.apache.commons.lang3.StringUtils.isNotBlank(command) &&
                command.equalsIgnoreCase(BaseCmd.getCommandNameByClass(CreateConsoleEndpointCmd.class))) {
            InetAddress addr = getClientAddress(req);
            String clientAddress = addr != null ? addr.getHostAddress() : null;
            params.put(ConsoleAccessUtils.CLIENT_INET_ADDRESS_KEY, new String[] {clientAddress});
        }
    }

    @Nullable
    private String saveLogString(String stringToLog) {
        return stringToLog == null ? null : stringToLog.replace(LOGGER_REPLACEMENTS, REPLACEMENT);
    }

    /**
     * Do a sanity check here to make sure the user hasn't already been deleted
     */
    private boolean requestChecksoutAsSane(HttpServletResponse resp, StringBuilder auditTrailSb, String responseType, Map<String, Object[]> params, HttpSession session, String command, Long userId, String account, Object accountObj) {
        if ((userId != null) && (account != null) && (accountObj != null) && apiServer.verifyUser(userId)) {
            if (command == null) {
                LOGGER.info("missing command, ignoring request...");
                auditTrailSb.append(" " + HttpServletResponse.SC_BAD_REQUEST + " " + "no command specified");
                final String serializedResponse = apiServer.getSerializedApiError(HttpServletResponse.SC_BAD_REQUEST, "no command specified", params, responseType);
                HttpUtils.writeHttpResponse(resp, serializedResponse, HttpServletResponse.SC_BAD_REQUEST, responseType, ApiServer.JSONContentType.value());
                return true;
            }
            final User user = entityMgr.findById(User.class, userId);
            CallContext.register(user, (Account) accountObj);
        } else {
            invalidateHttpSession(session, "Invalidate the session to ensure we won't allow a request across management server restarts if the userId was serialized to the stored session");

            auditTrailSb.append(" " + HttpServletResponse.SC_UNAUTHORIZED + " " + "unable to verify user credentials");
            final String serializedResponse =
                    apiServer.getSerializedApiError(HttpServletResponse.SC_UNAUTHORIZED, "unable to verify user credentials", params, responseType);
            HttpUtils.writeHttpResponse(resp, serializedResponse, HttpServletResponse.SC_UNAUTHORIZED, responseType, ApiServer.JSONContentType.value());
            return false;
        }
        return true;
    }

    private boolean invalidateHttpSessionIfNeeded(HttpServletRequest req, HttpServletResponse resp, StringBuilder auditTrailSb, String responseType, Map<String, Object[]> params, HttpSession session, String account) {
        ApiSessionKeyCheckOption sessionKeyCheckOption = EnumUtils.getEnumIgnoreCase(ApiSessionKeyCheckOption.class,
                ApiServer.ApiSessionKeyCheckLocations.value(), ApiSessionKeyCheckOption.CookieAndParameter);
        if (!HttpUtils.validateSessionKey(session, params, req.getCookies(), ApiConstants.SESSIONKEY, sessionKeyCheckOption)) {
            String msg = String.format("invalidating session %s for account %s", session.getId(), account);
            invalidateHttpSession(session, msg);
            auditTrailSb.append(" " + HttpServletResponse.SC_UNAUTHORIZED + " " + "unable to verify user credentials");
            final String serializedResponse =
                    apiServer.getSerializedApiError(HttpServletResponse.SC_UNAUTHORIZED, "unable to verify user credentials", params, responseType);
            HttpUtils.writeHttpResponse(resp, serializedResponse, HttpServletResponse.SC_UNAUTHORIZED, responseType, ApiServer.JSONContentType.value());
            return true;
        }
        return false;
    }

    /**
     * Echoes back every cookie on the request with Max-Age=0 so the browser drops them. Must be
     * called before the response is committed (e.g. before HttpServletResponse#sendRedirect),
     * otherwise the Set-Cookie headers are silently dropped by the servlet container.
     */
    public static void clearRequestCookies(HttpServletRequest req, HttpServletResponse resp) {
        final Cookie[] cookies = req.getCookies();
        if (cookies != null) {
            for (final Cookie cookie : cookies) {
                cookie.setValue("");
                cookie.setMaxAge(0);
                resp.addCookie(cookie);
            }
        }
    }

    public static void invalidateHttpSession(HttpSession session, String msg) {
        try {
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace(msg);
            }
            if (session == null) {
                return;
            }
            session.invalidate();
        } catch (final IllegalStateException ise) {
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace(String.format("failed to invalidate session %s", session.getId()));
            }
        }
    }

    private void setProjectContext(Map<String, Object[]> requestParameters) {
        final String[] command = (String[])requestParameters.get(ApiConstants.COMMAND);
        if (command == null) {
            LOGGER.info("missing command, ignoring request...");
            return;
        }

        final String commandName = command[0];
        CallContext.current().setApiName(commandName);
        for (Map.Entry<String, Object[]> entry: requestParameters.entrySet()) {
            if (entry.getKey().equals(ApiConstants.PROJECT_ID) || isSpecificAPI(commandName)) {
                String projectId = null;
                if (isSpecificAPI(commandName)) {
                    projectId = String.valueOf(requestParameters.entrySet().stream()
                            .filter(e -> e.getKey().equals(ApiConstants.ID))
                            .map(Map.Entry::getValue).findFirst().get()[0]);
                } else {
                    projectId = String.valueOf(entry.getValue()[0]);
                }
                Project project = projectDao.findByUuid(projectId);
                if (project != null) {
                    CallContext.current().setProject(project);
                }
            }
        }
    }

    private boolean isSpecificAPI(String commandName) {
        List<String> commands = Arrays.asList("suspendProject", "updateProject", "activateProject", "deleteProject");
        if (commands.contains(commandName)) {
            return true;
        }
        return false;
    }
    static boolean doUseForwardHeaders() {
        return Boolean.TRUE.equals(ApiServer.useForwardHeader.value());
    }

    static String[] proxyNets() {
        return ApiServer.proxyForwardList.value().split(",");
    }
    //This method will try to get login IP of user even if servlet is behind reverseProxy or loadBalancer
    public static InetAddress getClientAddress(final HttpServletRequest request) throws UnknownHostException {
        final String remote = request.getRemoteAddr();
        if (doUseForwardHeaders()) {
            final InetAddress remoteAddr = InetAddress.getByName(remote);
            if (NetUtils.isIpInCidrList(remoteAddr, proxyNets())) {
                for (String header : getClientAddressHeaders()) {
                    header = header.trim();
                    final String ip = getCorrectIPAddress(request.getHeader(header));
                    if (StringUtils.isNotBlank(ip)) {
                        LOGGER.debug("found ip {} in header {}", ip, header);
                        return InetAddress.getByName(ip);
                    }
                }
            }
        }
        LOGGER.trace("no ip found in headers, returning remote address {}.", remote);
        return InetAddress.getByName(remote);
    }

    private static String[] getClientAddressHeaders() {
        return ApiServer.listOfForwardHeaders.value().split(",");
    }

    private static String getCorrectIPAddress(String ip) {
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            return null;
        }
        if(NetUtils.isValidIp4(ip) || NetUtils.isValidIp6(ip)) {
            return ip;
        }
        //it could be possible to have multiple IPs in HTTP header, this happens if there are multiple proxy in between
        //the client and the servlet, so parse the client IP
        String[] ips = ip.split(",");
        for(String i : ips) {
            if(NetUtils.isValidIp4(i.trim()) || NetUtils.isValidIp6(i.trim())) {
                return i.trim();
            }
        }
        return null;
    }

    private String getCleanParamsString(Map<String, String[]> reqParams) {
        if (MapUtils.isEmpty(reqParams)) {
            return "";
        }

        StringBuilder cleanParamsString = new StringBuilder();
        for (Map.Entry<String, String[]> reqParam : reqParams.entrySet()) {
            if (org.apache.commons.lang3.StringUtils.isBlank(reqParam.getKey())) {
                continue;
            }

            cleanParamsString.append(reqParam.getKey());
            cleanParamsString.append("=");

            if (reqParam.getKey().toLowerCase().contains("password")
                    || reqParam.getKey().toLowerCase().contains("privatekey")
                    || reqParam.getKey().toLowerCase().contains("accesskey")
                    || reqParam.getKey().toLowerCase().contains("secretkey")) {
                cleanParamsString.append("\n");
                continue;
            }

            if (reqParam.getValue() == null || reqParam.getValue().length == 0) {
                cleanParamsString.append("\n");
                continue;
            }

            for (String param : reqParam.getValue()) {
                if (org.apache.commons.lang3.StringUtils.isBlank(param)) {
                    continue;
                }
                String cleanParamString = StringUtils.cleanString(param.trim());
                cleanParamsString.append(cleanParamString);
                cleanParamsString.append(" ");
            }
            cleanParamsString.append("\n");
        }

        return cleanParamsString.toString();
    }
}
