This is an automated email from the ASF dual-hosted git repository.

dahn pushed a commit to tag 4.19.1.2
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit 13dd6983428a535a5d401bce106dd5da9a1b802a
Author: Wei Zhou <weiz...@apache.org>
AuthorDate: Tue Sep 10 18:25:36 2024 +0200

    util: check JSESSIONID in cookies if user is passed
---
 .../api/command/ListAndSwitchSAMLAccountCmd.java   |   7 +-
 .../apache/cloudstack/saml/SAML2AuthManager.java   |   3 +
 .../cloudstack/saml/SAML2AuthManagerImpl.java      |   3 +-
 .../java/org/apache/cloudstack/saml/SAMLUtils.java |  25 ++++-
 .../command/ListAndSwitchSAMLAccountCmdTest.java   |  25 ++++-
 server/src/main/java/com/cloud/api/ApiServer.java  |  26 +++++-
 server/src/main/java/com/cloud/api/ApiServlet.java | 102 +++++++++++++--------
 test/integration/smoke/test_login.py               |   1 +
 ui/src/api/index.js                                |  10 ++
 ui/src/store/modules/user.js                       |   1 -
 utils/src/main/java/com/cloud/utils/HttpUtils.java |  42 +++++++--
 .../test/java/com/cloud/utils/HttpUtilsTest.java   |  86 ++++++++++++++---
 12 files changed, 266 insertions(+), 65 deletions(-)

diff --git 
a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java
 
b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java
index 25f056adf68..c2f81cd3356 100644
--- 
a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java
+++ 
b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmd.java
@@ -48,6 +48,7 @@ import org.apache.cloudstack.saml.SAML2AuthManager;
 import org.apache.cloudstack.saml.SAMLUtils;
 import org.apache.log4j.Logger;
 
+import com.cloud.api.ApiServer;
 import com.cloud.api.response.ApiResponseSerializer;
 import com.cloud.domain.Domain;
 import com.cloud.domain.dao.DomainDao;
@@ -60,6 +61,8 @@ import com.cloud.user.dao.UserAccountDao;
 import com.cloud.user.dao.UserDao;
 import com.cloud.utils.HttpUtils;
 
+import org.apache.commons.lang3.EnumUtils;
+
 @APICommand(name = "listAndSwitchSamlAccount", description = "Lists and 
switches to other SAML accounts owned by the SAML user", responseObject = 
SuccessResponse.class, requestHasSensitiveInfo = false, 
responseHasSensitiveInfo = false)
 public class ListAndSwitchSAMLAccountCmd extends BaseCmd implements 
APIAuthenticator {
     public static final Logger s_logger = 
Logger.getLogger(ListAndSwitchSAMLAccountCmd.class.getName());
@@ -104,7 +107,9 @@ public class ListAndSwitchSAMLAccountCmd extends BaseCmd 
implements APIAuthentic
                     params, responseType));
         }
 
-        if (!HttpUtils.validateSessionKey(session, params, req.getCookies(), 
ApiConstants.SESSIONKEY)) {
+        HttpUtils.ApiSessionKeyCheckOption sessionKeyCheckOption = 
EnumUtils.getEnumIgnoreCase(HttpUtils.ApiSessionKeyCheckOption.class,
+                ApiServer.ApiSessionKeyCheckLocations.value(), 
HttpUtils.ApiSessionKeyCheckOption.CookieAndParameter);
+        if (!HttpUtils.validateSessionKey(session, params, req.getCookies(), 
ApiConstants.SESSIONKEY, sessionKeyCheckOption)) {
             throw new ServerApiException(ApiErrorCode.UNAUTHORIZED, 
_apiServer.getSerializedApiError(ApiErrorCode.UNAUTHORIZED.getHttpCode(),
                     "Unauthorized session, please re-login",
                     params, responseType));
diff --git 
a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManager.java
 
b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManager.java
index 3a4030f9c0d..e10ea08012f 100644
--- 
a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManager.java
+++ 
b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManager.java
@@ -73,6 +73,9 @@ public interface SAML2AuthManager extends 
PluggableAPIAuthenticator, PluggableSe
     ConfigKey<Boolean> SAMLCheckSignature = new ConfigKey<Boolean>("Advanced", 
Boolean.class, "saml2.check.signature", "true",
             "When enabled (default and recommended), SAML2 signature checks 
are enforced and lack of signature in the SAML SSO response will cause login 
exception. Disabling this is not advisable but provided for backward 
compatibility for users who are able to accept the risks.", false);
 
+    ConfigKey<String> SAMLUserSessionKeyPathAttribute = new 
ConfigKey<String>("Advanced", String.class, "saml2.user.sessionkey.path", "",
+            "The Path attribute of sessionkey cookie when SAML users have 
logged in. If not set, it will be set to the path of SAML redirection URL 
(saml2.redirect.url).", true);
+
     SAMLProviderMetadata getSPMetadata();
     SAMLProviderMetadata getIdPMetadata(String entityId);
     Collection<SAMLProviderMetadata> getAllIdPMetadata();
diff --git 
a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java
 
b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java
index dfa76414fb7..aa1e0be91c7 100644
--- 
a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java
+++ 
b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java
@@ -542,6 +542,7 @@ public class SAML2AuthManagerImpl extends AdapterBase 
implements SAML2AuthManage
                 SAMLServiceProviderSingleSignOnURL, 
SAMLServiceProviderSingleLogOutURL,
                 SAMLCloudStackRedirectionUrl, SAMLUserAttributeName,
                 SAMLIdentityProviderMetadataURL, SAMLDefaultIdentityProviderId,
-                SAMLSignatureAlgorithm, SAMLAppendDomainSuffix, SAMLTimeout, 
SAMLCheckSignature};
+                SAMLSignatureAlgorithm, SAMLAppendDomainSuffix, SAMLTimeout, 
SAMLCheckSignature,
+                SAMLUserSessionKeyPathAttribute};
     }
 }
diff --git 
a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAMLUtils.java
 
b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAMLUtils.java
index f10bc891368..bb94c8af4c2 100644
--- 
a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAMLUtils.java
+++ 
b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAMLUtils.java
@@ -25,6 +25,8 @@ import java.io.IOException;
 import java.io.StringWriter;
 import java.io.UnsupportedEncodingException;
 import java.math.BigInteger;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.net.URLEncoder;
 import java.nio.charset.Charset;
 import java.security.InvalidKeyException;
@@ -101,7 +103,9 @@ import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.xml.sax.SAXException;
 
+import com.cloud.api.ApiServlet;
 import com.cloud.utils.HttpUtils;
+import com.cloud.utils.exception.CloudRuntimeException;
 
 public class SAMLUtils {
     public static final Logger s_logger = Logger.getLogger(SAMLUtils.class);
@@ -296,7 +300,26 @@ public class SAMLUtils {
             resp.addCookie(new Cookie("timezone", URLEncoder.encode(timezone, 
HttpUtils.UTF_8)));
         }
         resp.addCookie(new Cookie("userfullname", 
URLEncoder.encode(loginResponse.getFirstName() + " " + 
loginResponse.getLastName(), HttpUtils.UTF_8).replace("+", "%20")));
-        resp.addHeader("SET-COOKIE", 
String.format("%s=%s;HttpOnly;Path=/client/api", ApiConstants.SESSIONKEY, 
loginResponse.getSessionKey()));
+
+        String redirectUrl = 
SAML2AuthManager.SAMLCloudStackRedirectionUrl.value();
+        String path = SAML2AuthManager.SAMLUserSessionKeyPathAttribute.value();
+        String domain = null;
+        try {
+            URI redirectUri = new URI(redirectUrl);
+            domain = redirectUri.getHost();
+            if (StringUtils.isBlank(path)) {
+                path = redirectUri.getPath();
+            }
+            if (StringUtils.isBlank(path)) {
+                path = "/";
+            }
+        } catch (URISyntaxException ex) {
+            throw new CloudRuntimeException("Invalid URI: " + redirectUrl);
+        }
+        String sameSite = ApiServlet.getApiSessionKeySameSite();
+        String sessionKeyCookie = String.format("%s=%s;Domain=%s;Path=%s;%s", 
ApiConstants.SESSIONKEY, loginResponse.getSessionKey(), domain, path, sameSite);
+        s_logger.debug("Adding sessionkey cookie to response: " + 
sessionKeyCookie);
+        resp.addHeader("SET-COOKIE", sessionKeyCookie);
     }
 
     /**
diff --git 
a/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmdTest.java
 
b/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmdTest.java
index b4d230e3cd6..729334d22ce 100644
--- 
a/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmdTest.java
+++ 
b/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/api/command/ListAndSwitchSAMLAccountCmdTest.java
@@ -27,6 +27,7 @@ import java.net.InetAddress;
 import java.util.HashMap;
 import java.util.Map;
 
+import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
@@ -88,6 +89,9 @@ public class ListAndSwitchSAMLAccountCmdTest extends TestCase 
{
     @Mock
     HttpServletRequest req;
 
+    final String sessionId = "node0xxxxxxxxxxxxx";
+    Cookie[] cookies;
+
     @Test
     public void testListAndSwitchSAMLAccountCmd() throws Exception {
         // Setup
@@ -95,6 +99,7 @@ public class ListAndSwitchSAMLAccountCmdTest extends TestCase 
{
         final String sessionKeyValue = "someSessionIDValue";
         
Mockito.when(session.getAttribute(ApiConstants.SESSIONKEY)).thenReturn(sessionKeyValue);
         Mockito.when(session.getAttribute("userid")).thenReturn(2L);
+        Mockito.when(session.getId()).thenReturn(sessionId);
         params.put(ApiConstants.USER_ID, new String[]{"2"});
         params.put(ApiConstants.DOMAIN_ID, new String[]{"1"});
         Mockito.when(userDao.findByUuid(anyString())).thenReturn(new 
UserVO(2L));
@@ -146,7 +151,25 @@ public class ListAndSwitchSAMLAccountCmdTest extends 
TestCase {
             Mockito.verify(accountService, 
Mockito.times(0)).getUserAccountById(Mockito.anyLong());
         }
 
-        // valid sessionkey value test
+        // valid sessionkey value and invalid JSESSIONID test
+        cookies = new Cookie[2];
+        cookies[0] = new Cookie(ApiConstants.SESSIONKEY, sessionKeyValue);
+        cookies[1] = new Cookie("JSESSIONID", "invalid-JSESSIONID");
+        Mockito.when(req.getCookies()).thenReturn(cookies);
+        params.put(ApiConstants.SESSIONKEY, new String[]{sessionKeyValue});
+        try {
+            cmd.authenticate("command", params, session, null, 
HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
+        } catch (ServerApiException exception) {
+            assertEquals(exception.getErrorCode(), ApiErrorCode.UNAUTHORIZED);
+        } finally {
+            Mockito.verify(accountService, 
Mockito.times(0)).getUserAccountById(Mockito.anyLong());
+        }
+
+        // valid sessionkey value and valid JSESSIONID test
+        cookies = new Cookie[2];
+        cookies[0] = new Cookie(ApiConstants.SESSIONKEY, sessionKeyValue);
+        cookies[1] = new Cookie("JSESSIONID", sessionId + ".node0");
+        Mockito.when(req.getCookies()).thenReturn(cookies);
         params.put(ApiConstants.SESSIONKEY, new String[]{sessionKeyValue});
         try {
             cmd.authenticate("command", params, session, null, 
HttpUtils.RESPONSE_TYPE_JSON, new StringBuilder(), req, resp);
diff --git a/server/src/main/java/com/cloud/api/ApiServer.java 
b/server/src/main/java/com/cloud/api/ApiServer.java
index b1a04932cf9..d68f42470d5 100644
--- a/server/src/main/java/com/cloud/api/ApiServer.java
+++ b/server/src/main/java/com/cloud/api/ApiServer.java
@@ -33,6 +33,7 @@ import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
+import java.util.EnumSet;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -47,6 +48,7 @@ import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 import javax.crypto.Mac;
 import javax.crypto.spec.SecretKeySpec;
@@ -168,6 +170,8 @@ import com.cloud.user.UserVO;
 import com.cloud.utils.ConstantTimeComparator;
 import com.cloud.utils.DateUtil;
 import com.cloud.utils.HttpUtils;
+import com.cloud.utils.HttpUtils.ApiSessionKeySameSite;
+import com.cloud.utils.HttpUtils.ApiSessionKeyCheckOption;
 import com.cloud.utils.Pair;
 import com.cloud.utils.ReflectUtil;
 import com.cloud.utils.StringUtils;
@@ -306,6 +310,24 @@ public class ApiServer extends ManagerBase implements 
HttpRequestHandler, ApiSer
             , true
             , ConfigKey.Scope.Global);
 
+    static final ConfigKey<String> ApiSessionKeyCookieSameSiteSetting = new 
ConfigKey<>(String.class
+            , "api.sessionkey.cookie.samesite"
+            , ConfigKey.CATEGORY_ADVANCED
+            , ApiSessionKeySameSite.Lax.name()
+            , "The SameSite attribute of cookie 'sessionkey'. Valid options 
are: Lax (default), Strict, NoneAndSecure and Null."
+            , true
+            , ConfigKey.Scope.Global, null, null, null, null, null, 
ConfigKey.Kind.Select,
+            
EnumSet.allOf(ApiSessionKeySameSite.class).stream().map(Enum::toString).collect(Collectors.joining(",
 ")));
+
+    public static final ConfigKey<String> ApiSessionKeyCheckLocations = new 
ConfigKey<>(String.class
+            , "api.sessionkey.check.locations"
+            , ConfigKey.CATEGORY_ADVANCED
+            , ApiSessionKeyCheckOption.CookieAndParameter.name()
+            , "The locations of 'sessionkey' during the validation of the API 
requests. Valid options are: CookieOrParameter, ParameterOnly, 
CookieAndParameter (default)."
+            , true
+            , ConfigKey.Scope.Global, null, null, null, null, null, 
ConfigKey.Kind.Select,
+            
EnumSet.allOf(ApiSessionKeyCheckOption.class).stream().map(Enum::toString).collect(Collectors.joining(",
 ")));
+
     @Override
     public boolean configure(final String name, final Map<String, Object> 
params) throws ConfigurationException {
         messageBus.subscribe(AsyncJob.Topics.JOB_EVENT_PUBLISH, 
MessageDispatcher.getDispatcher(this));
@@ -1531,7 +1553,9 @@ public class ApiServer extends ManagerBase implements 
HttpRequestHandler, ApiSer
                 JSONDefaultContentType,
                 proxyForwardList,
                 useForwardHeader,
-                listOfForwardHeaders
+                listOfForwardHeaders,
+                ApiSessionKeyCookieSameSiteSetting,
+                ApiSessionKeyCheckLocations
         };
     }
 }
diff --git a/server/src/main/java/com/cloud/api/ApiServlet.java 
b/server/src/main/java/com/cloud/api/ApiServlet.java
index e719238afef..d9654f03916 100644
--- a/server/src/main/java/com/cloud/api/ApiServlet.java
+++ b/server/src/main/java/com/cloud/api/ApiServlet.java
@@ -47,6 +47,7 @@ import org.apache.cloudstack.context.CallContext;
 import org.apache.cloudstack.managed.context.ManagedContext;
 import org.apache.cloudstack.utils.consoleproxy.ConsoleAccessUtils;
 import org.apache.log4j.Logger;
+import org.apache.commons.lang3.EnumUtils;
 import org.jetbrains.annotations.Nullable;
 import org.springframework.stereotype.Component;
 import org.springframework.web.context.support.SpringBeanAutowiringSupport;
@@ -63,13 +64,15 @@ 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 {
-    public static final Logger s_logger = 
Logger.getLogger(ApiServlet.class.getName());
+    public static final Logger LOGGER = 
Logger.getLogger(ApiServlet.class.getName());
     private static final Logger s_accessLogger = Logger.getLogger("apiserver." 
+ ApiServlet.class.getName());
     private static final String REPLACEMENT = "_";
     private static final String LOG_REPLACEMENTS = "[\n\r\t]";
@@ -127,7 +130,7 @@ public class ApiServlet extends HttpServlet {
                     String value = decodeUtf8(paramTokens[1]);
                     params.put(name, new String[] {value});
                 } else {
-                    s_logger.debug("Invalid parameter in URL found. param: " + 
param);
+                    LOGGER.debug("Invalid parameter in URL found. param: " + 
param);
                 }
             }
         }
@@ -156,7 +159,7 @@ public class ApiServlet extends HttpServlet {
             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));
-                s_logger.warn(message);
+                LOGGER.warn(message);
             }
         });
 
@@ -167,7 +170,7 @@ public class ApiServlet extends HttpServlet {
         try {
             remoteAddress = getClientAddress(req);
         } catch (UnknownHostException e) {
-            s_logger.warn("UnknownHostException when trying to lookup remote 
IP-Address. This should never happen. Blocking request.", 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);
@@ -191,17 +194,17 @@ public class ApiServlet extends HttpServlet {
         // logging the request start and end in management log for easy 
debugging
         String reqStr = "";
         String cleanQueryString = 
StringUtils.cleanString(req.getQueryString());
-        if (s_logger.isDebugEnabled()) {
+        if (LOGGER.isDebugEnabled()) {
             reqStr = auditTrailSb.toString() + " " + cleanQueryString;
-            s_logger.debug("===START=== " + reqStr);
+            LOGGER.debug("===START=== " + reqStr);
         }
 
         try {
             resp.setContentType(HttpUtils.XML_CONTENT_TYPE);
 
             HttpSession session = req.getSession(false);
-            if (s_logger.isTraceEnabled()) {
-                s_logger.trace(String.format("session found: %s", session));
+            if (LOGGER.isTraceEnabled()) {
+                LOGGER.trace(String.format("session found: %s", session));
             }
             final Object[] responseTypeParam = 
params.get(ApiConstants.RESPONSE);
             if (responseTypeParam != null) {
@@ -212,10 +215,10 @@ public class ApiServlet extends HttpServlet {
             final String command = commandObj == null ? null : (String) 
commandObj[0];
             final Object[] userObj = params.get(ApiConstants.USERNAME);
             String username = userObj == null ? null : (String)userObj[0];
-            if (s_logger.isTraceEnabled()) {
+            if (LOGGER.isTraceEnabled()) {
                 String logCommand = saveLogString(command);
                 String logName = saveLogString(username);
-                s_logger.trace(String.format("command %s processing for user 
\"%s\"",
+                LOGGER.trace(String.format("command %s processing for user 
\"%s\"",
                         logCommand,
                         logName));
             }
@@ -238,25 +241,26 @@ public class ApiServlet extends HttpServlet {
 
                         if (ApiServer.EnableSecureSessionCookie.value()) {
                             resp.setHeader("SET-COOKIE", 
String.format("JSESSIONID=%s;Secure;HttpOnly;Path=/client", session.getId()));
-                            if (s_logger.isDebugEnabled()) {
-                                s_logger.debug("Session cookie is marked 
secure!");
+                            if (LOGGER.isDebugEnabled()) {
+                                LOGGER.debug("Session cookie is marked 
secure!");
                             }
                         }
                     }
 
                     try {
-                        if (s_logger.isTraceEnabled()) {
-                            
s_logger.trace(String.format("apiAuthenticator.authenticate(%s, params[%d], %s, 
%s, %s, %s, %s,%s)",
+                        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) {
-                            resp.addHeader("SET-COOKIE", 
String.format("%s=%s;HttpOnly", ApiConstants.SESSIONKEY, 
session.getAttribute(ApiConstants.SESSIONKEY)));
+                            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();
-                        s_logger.debug("Authentication failure: " + 
e.getMessage());
+                        LOGGER.debug("Authentication failure: " + 
e.getMessage());
                     }
 
                     if (apiAuthenticator.getAPIType() == 
APIAuthenticationType.LOGOUT_API) {
@@ -289,7 +293,7 @@ public class ApiServlet extends HttpServlet {
                     return;
                 }
             } else {
-                s_logger.trace("no command available");
+                LOGGER.trace("no command available");
             }
             auditTrailSb.append(cleanQueryString);
             final boolean isNew = ((session == null) ? true : session.isNew());
@@ -298,15 +302,15 @@ public class ApiServlet extends HttpServlet {
             // we no longer rely on web-session here, verifyRequest will 
populate user/account information
             // if a API key exists
 
-            if (isNew && s_logger.isTraceEnabled()) {
-                s_logger.trace(String.format("new session: %s", session));
+            if (isNew && LOGGER.isTraceEnabled()) {
+                LOGGER.trace(String.format("new session: %s", session));
             }
 
             if (!isNew && 
(command.equalsIgnoreCase(ValidateUserTwoFactorAuthenticationCodeCmd.APINAME) 
|| (!skip2FAcheckForAPIs(command) && !skip2FAcheckForUser(session)))) {
-                s_logger.debug("Verifying two factor authentication");
+                LOGGER.debug("Verifying two factor authentication");
                 boolean success = verify2FA(session, command, auditTrailSb, 
params, remoteAddress, responseType, req, resp);
                 if (!success) {
-                    s_logger.debug("Verification of two factor authentication 
failed");
+                    LOGGER.debug("Verification of two factor authentication 
failed");
                     return;
                 }
             }
@@ -319,8 +323,8 @@ public class ApiServlet extends HttpServlet {
                 if (account != null) {
                     if (invalidateHttpSessionIfNeeded(req, resp, auditTrailSb, 
responseType, params, session, account)) return;
                 } else {
-                    if (s_logger.isDebugEnabled()) {
-                        s_logger.debug("no account, this request will be 
validated through apikey(%s)/signature");
+                    if (LOGGER.isDebugEnabled()) {
+                        LOGGER.debug("no account, this request will be 
validated through apikey(%s)/signature");
                     }
                 }
 
@@ -330,8 +334,8 @@ public class ApiServlet extends HttpServlet {
                 CallContext.register(accountMgr.getSystemUser(), 
accountMgr.getSystemAccount());
             }
             setProjectContext(params);
-            if (s_logger.isTraceEnabled()) {
-                s_logger.trace(String.format("verifying request for user %s 
from %s with %d parameters",
+            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)) {
@@ -362,18 +366,34 @@ public class ApiServlet extends HttpServlet {
             HttpUtils.writeHttpResponse(resp, serializedResponseText, 
se.getErrorCode().getHttpCode(), responseType, 
ApiServer.JSONcontentType.value());
             auditTrailSb.append(" " + se.getErrorCode() + " " + 
se.getDescription());
         } catch (final Exception ex) {
-            s_logger.error("unknown exception writing api response", ex);
+            LOGGER.error("unknown exception writing api response", ex);
             auditTrailSb.append(" unknown exception writing api response");
         } finally {
             s_accessLogger.info(auditTrailSb.toString());
-            if (s_logger.isDebugEnabled()) {
-                s_logger.debug("===END=== " + reqStr);
+            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 boolean checkIfAuthenticatorIsOf2FA(String command) {
         boolean verify2FA = false;
         APIAuthenticator apiAuthenticator = 
authManager.getAPIAuthenticator(command);
@@ -402,7 +422,7 @@ public class ApiServlet extends HttpServlet {
         Long userId = (Long) session.getAttribute("userid");
         boolean is2FAverified = (boolean) 
session.getAttribute(ApiConstants.IS_2FA_VERIFIED);
         if (is2FAverified) {
-            s_logger.debug(String.format("Two factor authentication is already 
verified for the user %d, so skipping", userId));
+            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);
@@ -433,7 +453,7 @@ public class ApiServlet extends HttpServlet {
                 HttpUtils.writeHttpResponse(resp, responseString, 
HttpServletResponse.SC_OK, responseType, ApiServer.JSONcontentType.value());
                 verify2FA = true;
             } else {
-                s_logger.error("Cannot find API authenticator while verifying 
2FA");
+                LOGGER.error("Cannot find API authenticator while verifying 
2FA");
                 auditTrailSb.append(" Cannot find API authenticator while 
verifying 2FA");
                 verify2FA = false;
             }
@@ -457,7 +477,7 @@ public class ApiServlet extends HttpServlet {
                 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.";
             }
-            s_logger.error(errorMsg);
+            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);
@@ -488,7 +508,7 @@ public class ApiServlet extends HttpServlet {
     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) {
-                s_logger.info("missing command, ignoring request...");
+                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());
@@ -509,7 +529,9 @@ public class ApiServlet extends HttpServlet {
     }
 
     private boolean invalidateHttpSessionIfNeeded(HttpServletRequest req, 
HttpServletResponse resp, StringBuilder auditTrailSb, String responseType, 
Map<String, Object[]> params, HttpSession session, String account) {
-        if (!HttpUtils.validateSessionKey(session, params, req.getCookies(), 
ApiConstants.SESSIONKEY)) {
+        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");
@@ -523,13 +545,13 @@ public class ApiServlet extends HttpServlet {
 
     public static void invalidateHttpSession(HttpSession session, String msg) {
         try {
-            if (s_logger.isTraceEnabled()) {
-                s_logger.trace(msg);
+            if (LOGGER.isTraceEnabled()) {
+                LOGGER.trace(msg);
             }
             session.invalidate();
         } catch (final IllegalStateException ise) {
-            if (s_logger.isTraceEnabled()) {
-                s_logger.trace(String.format("failed to invalidate session 
%s", session.getId()));
+            if (LOGGER.isTraceEnabled()) {
+                LOGGER.trace(String.format("failed to invalidate session %s", 
session.getId()));
             }
         }
     }
@@ -537,7 +559,7 @@ public class ApiServlet extends HttpServlet {
     private void setProjectContext(Map<String, Object[]> requestParameters) {
         final String[] command = 
(String[])requestParameters.get(ApiConstants.COMMAND);
         if (command == null) {
-            s_logger.info("missing command, ignoring request...");
+            LOGGER.info("missing command, ignoring request...");
             return;
         }
 
@@ -585,14 +607,14 @@ public class ApiServlet extends HttpServlet {
                     header = header.trim();
                     ip = getCorrectIPAddress(request.getHeader(header));
                     if (StringUtils.isNotBlank(ip)) {
-                        s_logger.debug(String.format("found ip %s in header %s 
", ip, header));
+                        LOGGER.debug(String.format("found ip %s in header %s 
", ip, header));
                         break;
                     }
                 } // no address found in header so ip is blank and use remote 
addr
             } // else not an allowed proxy address, ip is blank and use remote 
addr
         }
         if (StringUtils.isBlank(ip)) {
-            s_logger.trace(String.format("no ip found in headers, returning 
remote address %s.", pretender.getHostAddress()));
+            LOGGER.trace(String.format("no ip found in headers, returning 
remote address %s.", pretender.getHostAddress()));
             return pretender;
         }
 
diff --git a/test/integration/smoke/test_login.py 
b/test/integration/smoke/test_login.py
index 40d8349a13d..acd6c4334ac 100644
--- a/test/integration/smoke/test_login.py
+++ b/test/integration/smoke/test_login.py
@@ -133,6 +133,7 @@ class TestLogin(cloudstackTestCase):
             args["command"] = 'listUsers'
             args["listall"] = 'true'
             args["response"] = "json"
+            args["sessionkey"] = response.json()['loginresponse']['sessionkey']
             response = session.get(self.server_url, params=args)
             self.assertEqual(
                 response.status_code,
diff --git a/ui/src/api/index.js b/ui/src/api/index.js
index 14432010738..7ab87780a9d 100644
--- a/ui/src/api/index.js
+++ b/ui/src/api/index.js
@@ -15,8 +15,13 @@
 // specific language governing permissions and limitations
 // under the License.
 
+import Cookies from 'js-cookie'
 import { axios, sourceToken } from '@/utils/request'
 import { message, notification } from 'ant-design-vue'
+import { vueProps } from '@/vue-app'
+import {
+  ACCESS_TOKEN
+} from '@/store/mutation-types'
 
 export function api (command, args = {}, method = 'GET', data = {}) {
   let params = {}
@@ -30,6 +35,11 @@ export function api (command, args = {}, method = 'GET', 
data = {}) {
     })
   }
 
+  const sessionkey = vueProps.$localStorage.get(ACCESS_TOKEN) || 
Cookies.get('sessionkey')
+  if (sessionkey) {
+    args.sessionkey = sessionkey
+  }
+
   return axios({
     params: {
       ...args
diff --git a/ui/src/store/modules/user.js b/ui/src/store/modules/user.js
index 08a0c340c64..46a1905619f 100644
--- a/ui/src/store/modules/user.js
+++ b/ui/src/store/modules/user.js
@@ -24,7 +24,6 @@ import router from '@/router'
 import store from '@/store'
 import { oauthlogin, login, logout, api } from '@/api'
 import { i18n } from '@/locales'
-import { sourceToken } from '@/utils/request'
 
 import {
   ACCESS_TOKEN,
diff --git a/utils/src/main/java/com/cloud/utils/HttpUtils.java 
b/utils/src/main/java/com/cloud/utils/HttpUtils.java
index a5d9f6a16b6..cc97bf4ba15 100644
--- a/utils/src/main/java/com/cloud/utils/HttpUtils.java
+++ b/utils/src/main/java/com/cloud/utils/HttpUtils.java
@@ -37,6 +37,14 @@ public class HttpUtils {
     public static final String JSON_CONTENT_TYPE = "application/json; 
charset=UTF-8";
     public static final String XML_CONTENT_TYPE = "text/xml; charset=UTF-8";
 
+    public enum ApiSessionKeySameSite {
+        Lax, Strict, NoneAndSecure, Null
+    }
+
+    public enum ApiSessionKeyCheckOption {
+        CookieOrParameter, ParameterOnly, CookieAndParameter
+    }
+
     public static void addSecurityHeaders(final HttpServletResponse resp) {
         if (resp.containsHeader("X-Content-Type-Options")) {
             resp.setHeader("X-Content-Type-Options", "nosniff");
@@ -103,23 +111,43 @@ public class HttpUtils {
         return null;
     }
 
-    public static boolean validateSessionKey(final HttpSession session, final 
Map<String, Object[]> params, final Cookie[] cookies, final String 
sessionKeyString) {
+    public static boolean validateSessionKey(final HttpSession session, final 
Map<String, Object[]> params, final Cookie[] cookies, final String 
sessionKeyString, final ApiSessionKeyCheckOption apiSessionKeyCheckLocations) {
         if (session == null || sessionKeyString == null) {
             return false;
         }
+        final String jsessionidFromCookie = HttpUtils.findCookie(cookies, 
"JSESSIONID");
+        if (jsessionidFromCookie == null
+                || !(jsessionidFromCookie.startsWith(session.getId() + '.'))) {
+            s_logger.error("JSESSIONID from cookie is invalid.");
+            return false;
+        }
         final String sessionKey = (String) 
session.getAttribute(sessionKeyString);
+        if (sessionKey == null) {
+            s_logger.error("sessionkey attribute of the session is null.");
+            return false;
+        }
         final String sessionKeyFromCookie = HttpUtils.findCookie(cookies, 
sessionKeyString);
+        boolean isSessionKeyFromCookieValid = sessionKeyFromCookie != null && 
sessionKey.equals(sessionKeyFromCookie);
+
         String[] sessionKeyFromParams = null;
         if (params != null) {
             sessionKeyFromParams = (String[]) params.get(sessionKeyString);
         }
-        if ((sessionKey == null)
-                || (sessionKeyFromParams == null && sessionKeyFromCookie == 
null)
-                || (sessionKeyFromParams != null && 
!sessionKey.equals(sessionKeyFromParams[0]))
-                || (sessionKeyFromCookie != null && 
!sessionKey.equals(sessionKeyFromCookie))) {
-            return false;
+        boolean isSessionKeyFromParamsValid = sessionKeyFromParams != null && 
sessionKey.equals(sessionKeyFromParams[0]);
+
+        switch (apiSessionKeyCheckLocations) {
+            case CookieOrParameter:
+                return (sessionKeyFromCookie != null || sessionKeyFromParams 
!= null)
+                        && (sessionKeyFromCookie == null || 
isSessionKeyFromCookieValid)
+                        && (sessionKeyFromParams == null || 
isSessionKeyFromParamsValid);
+            case ParameterOnly:
+                return sessionKeyFromParams != null && 
isSessionKeyFromParamsValid
+                        && (sessionKeyFromCookie == null || 
isSessionKeyFromCookieValid);
+            case CookieAndParameter:
+            default:
+                return sessionKeyFromCookie != null && 
isSessionKeyFromCookieValid
+                        && sessionKeyFromParams != null && 
isSessionKeyFromParamsValid;
         }
-        return true;
     }
 
 }
diff --git a/utils/src/test/java/com/cloud/utils/HttpUtilsTest.java 
b/utils/src/test/java/com/cloud/utils/HttpUtilsTest.java
index e10a5a36b27..e94724ce3d6 100644
--- a/utils/src/test/java/com/cloud/utils/HttpUtilsTest.java
+++ b/utils/src/test/java/com/cloud/utils/HttpUtilsTest.java
@@ -60,35 +60,97 @@ public class HttpUtilsTest {
         final String sessionKeyValue = "randomUniqueSessionID";
 
         // session and sessionKeyString null test
-        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString));
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieOrParameter));
         sessionKeyString =  "sessionkey";
-        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString));
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieOrParameter));
 
         // param and cookie null test
         session = new MockHttpSession();
+        final String sessionId = session.getId();
         session.setAttribute(sessionKeyString, sessionKeyValue);
-        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString));
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieOrParameter));
 
-        // param null, cookies not null test
+        // param null, cookies not null test (JSESSIONID is null)
         params = null;
         cookies = new Cookie[]{new Cookie(sessionKeyString, sessionKeyValue)};
-        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
"randomString"));
-        assertTrue(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString));
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
"randomString", HttpUtils.ApiSessionKeyCheckOption.CookieOrParameter));
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieOrParameter));
+
+        // param null, cookies not null test (JSESSIONID is not null and 
matches)
+        cookies = new Cookie[2];
+        cookies[0] = new Cookie(sessionKeyString, sessionKeyValue);
+        cookies[1] = new Cookie("JSESSIONID", sessionId + ".node0");
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
"randomString", HttpUtils.ApiSessionKeyCheckOption.CookieOrParameter));
+
+        // param null, cookies not null test (JSESSIONID is not null but 
mismatches)
+        cookies = new Cookie[2];
+        cookies[0] = new Cookie(sessionKeyString, sessionKeyValue);
+        cookies[1] = new Cookie("JSESSIONID", "node0xxxxxxxxxxxxx.node0");
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
"randomString", HttpUtils.ApiSessionKeyCheckOption.CookieOrParameter));
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieOrParameter));
 
         // param not null, cookies null test
         params = new HashMap<String, Object[]>();
         params.put(sessionKeyString, new String[]{"randomString"});
         cookies = null;
-        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString));
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieOrParameter));
         params.put(sessionKeyString, new String[]{sessionKeyValue});
-        assertTrue(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString));
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieOrParameter));
 
-        // both param and cookies not null test
+        // both param and cookies not null test (JSESSIONID is null)
         params = new HashMap<String, Object[]>();
-        cookies = new Cookie[]{new Cookie(sessionKeyString, sessionKeyValue)};
+        cookies = new Cookie[2];
+        cookies[0] = new Cookie(sessionKeyString, sessionKeyValue);
         params.put(sessionKeyString, new String[]{"incorrectValue"});
-        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString));
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieOrParameter));
         params.put(sessionKeyString, new String[]{sessionKeyValue});
-        assertTrue(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString));
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieOrParameter));
+
+        // both param and cookies not null test (JSESSIONID is not null but 
mismatches)
+        params = new HashMap<String, Object[]>();
+        cookies = new Cookie[2];
+        cookies[0] = new Cookie(sessionKeyString, sessionKeyValue);
+        cookies[1] = new Cookie("JSESSIONID", "node0xxxxxxxxxxxxx.node0");
+        params.put(sessionKeyString, new String[]{"incorrectValue"});
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieOrParameter));
+        params.put(sessionKeyString, new String[]{sessionKeyValue});
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieOrParameter));
+
+        // both param and cookies not null test (JSESSIONID is not null amd 
matches)
+        params = new HashMap<String, Object[]>();
+        cookies = new Cookie[2];
+        cookies[0] = new Cookie(sessionKeyString, sessionKeyValue);
+        cookies[1] = new Cookie("JSESSIONID", sessionId + ".node0");
+        params.put(sessionKeyString, new String[]{"incorrectValue"});
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieOrParameter));
+        params.put(sessionKeyString, new String[]{sessionKeyValue});
+        assertTrue(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieOrParameter));
+
+        // param not null, cookies null test (JSESSIONID is not null amd 
matches)
+        params = new HashMap<String, Object[]>();
+        cookies = new Cookie[1];
+        cookies[0] = new Cookie("JSESSIONID", sessionId + ".node0");
+        params.put(sessionKeyString, new String[]{"incorrectValue"});
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.ParameterOnly));
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieAndParameter));
+        params.put(sessionKeyString, new String[]{sessionKeyValue});
+        assertTrue(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.ParameterOnly));
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieAndParameter));
+
+        // param not null (correct), cookies not null test (correct)
+        cookies = new Cookie[2];
+        cookies[0] = new Cookie(sessionKeyString, sessionKeyValue);
+        cookies[1] = new Cookie("JSESSIONID", sessionId + ".node0");
+        assertTrue(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieOrParameter));
+        assertTrue(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.ParameterOnly));
+        assertTrue(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieAndParameter));
+
+        // param not null (correct), cookies not null test (wrong)
+        cookies = new Cookie[2];
+        cookies[0] = new Cookie(sessionKeyString, "incorrectValue");
+        cookies[1] = new Cookie("JSESSIONID", sessionId + ".node0");
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieOrParameter));
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.ParameterOnly));
+        assertFalse(HttpUtils.validateSessionKey(session, params, cookies, 
sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieAndParameter));
     }
 }


Reply via email to