You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by sm...@apache.org on 2022/08/26 07:52:51 UTC

[knox] branch master updated: KNOX-2790 - Added a new funtion to verifier, this way the session lim… (#624)

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

smolnar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git


The following commit(s) were added to refs/heads/master by this push:
     new 71e073fbf KNOX-2790 - Added a new funtion to verifier, this way the session lim… (#624)
71e073fbf is described below

commit 71e073fbf94bbeeb62ad087f90a9e4968aac107e
Author: MrtnBalazs <77...@users.noreply.github.com>
AuthorDate: Fri Aug 26 09:52:45 2022 +0200

    KNOX-2790 - Added a new funtion to verifier, this way the session lim… (#624)
---
 .../org/apache/knox/gateway/GatewayMessages.java   |   3 +
 .../control/EmptyConcurrentSessionVerifier.java    |   7 +-
 .../control/InMemoryConcurrentSessionVerifier.java |  39 +++++++-
 .../InMemoryConcurrentSessionVerifierTest.java     | 104 ++++++++++++---------
 .../gateway/service/knoxsso/WebSSOResource.java    |  22 +++--
 .../service/knoxsso/WebSSOResourceTest.java        |   9 +-
 .../session/control/ConcurrentSessionVerifier.java |  15 ++-
 7 files changed, 137 insertions(+), 62 deletions(-)

diff --git a/gateway-server/src/main/java/org/apache/knox/gateway/GatewayMessages.java b/gateway-server/src/main/java/org/apache/knox/gateway/GatewayMessages.java
index ba0c7e43f..aa2130fbc 100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/GatewayMessages.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/GatewayMessages.java
@@ -722,6 +722,9 @@ public interface GatewayMessages {
   @Message(level = MessageLevel.ERROR, text = "ConcurrentSessionVerifier got blank username for verification.")
   void errorVerifyingUserBlankUsername();
 
+  @Message(level = MessageLevel.ERROR, text = "ConcurrentSessionVerifier got blank username for token registration.")
+  void errorRegisteringTokenForBlankUsername();
+
   @Message(level = MessageLevel.WARN, text = "InMemoryConcurrentSessionVerifier is used and privileged user group is not configured! Non-privileged limit applies to all users (except the unlimited group).")
   void privilegedUserGroupIsNotConfigured();
 }
diff --git a/gateway-server/src/main/java/org/apache/knox/gateway/session/control/EmptyConcurrentSessionVerifier.java b/gateway-server/src/main/java/org/apache/knox/gateway/session/control/EmptyConcurrentSessionVerifier.java
index 856e18670..7c8155a85 100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/session/control/EmptyConcurrentSessionVerifier.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/session/control/EmptyConcurrentSessionVerifier.java
@@ -40,7 +40,12 @@ public class EmptyConcurrentSessionVerifier implements ConcurrentSessionVerifier
   }
 
   @Override
-  public boolean verifySessionForUser(String username, JWT JWToken) {
+  public boolean verifySessionForUser(String username) {
+    return true;
+  }
+
+  @Override
+  public boolean registerToken(String username, JWT jwtToken) {
     return true;
   }
 
diff --git a/gateway-server/src/main/java/org/apache/knox/gateway/session/control/InMemoryConcurrentSessionVerifier.java b/gateway-server/src/main/java/org/apache/knox/gateway/session/control/InMemoryConcurrentSessionVerifier.java
index 9c8d8a058..b692cdc4a 100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/session/control/InMemoryConcurrentSessionVerifier.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/session/control/InMemoryConcurrentSessionVerifier.java
@@ -51,10 +51,16 @@ public class InMemoryConcurrentSessionVerifier implements ConcurrentSessionVerif
   private long cleaningPeriod;
   private final ScheduledExecutorService expiredTokenRemover = Executors.newSingleThreadScheduledExecutor();
 
+  /**
+   * This function is used after the verifySessionForUser function.
+   * It checks the session limits even though verifySessionForUser already checked them,
+   * because in high stress situations there might be some threads which get verified even though they are over the limit in
+   * verifySessionForUser function, so we catch them here.
+   */
   @Override
-  public boolean verifySessionForUser(String username, JWT jwtToken) {
+  public boolean registerToken(String username, JWT jwtToken) {
     if (StringUtils.isBlank(username)) {
-      LOG.errorVerifyingUserBlankUsername();
+      LOG.errorRegisteringTokenForBlankUsername();
       return false;
     }
     if (unlimitedUsers.contains(username)) {
@@ -63,8 +69,7 @@ public class InMemoryConcurrentSessionVerifier implements ConcurrentSessionVerif
 
     sessionCountModifyLock.lock();
     try {
-      int validTokenNumber = countValidTokensForUser(username);
-      if (privilegedUserCheckLimitReached(username, validTokenNumber) || nonPrivilegedUserCheckLimitReached(username, validTokenNumber)) {
+      if (checkLimitReached(username)) {
         return false;
       }
       concurrentSessionCounter.putIfAbsent(username, new HashSet<>());
@@ -75,6 +80,32 @@ public class InMemoryConcurrentSessionVerifier implements ConcurrentSessionVerif
     return true;
   }
 
+  @Override
+  public boolean verifySessionForUser(String username) {
+    if (StringUtils.isBlank(username)) {
+      LOG.errorVerifyingUserBlankUsername();
+      return false;
+    }
+    if (unlimitedUsers.contains(username)) {
+      return true;
+    }
+
+    sessionCountModifyLock.lock();
+    try {
+      if (checkLimitReached(username)) {
+        return false;
+      }
+    } finally {
+      sessionCountModifyLock.unlock();
+    }
+    return true;
+  }
+
+  private boolean checkLimitReached(String username) {
+    int validTokenNumber = countValidTokensForUser(username);
+    return privilegedUserCheckLimitReached(username, validTokenNumber) || nonPrivilegedUserCheckLimitReached(username, validTokenNumber);
+  }
+
   int countValidTokensForUser(String username) {
     return (int) concurrentSessionCounter
             .getOrDefault(username, Collections.emptySet())
diff --git a/gateway-server/src/test/java/org/apache/knox/gateway/session/control/InMemoryConcurrentSessionVerifierTest.java b/gateway-server/src/test/java/org/apache/knox/gateway/session/control/InMemoryConcurrentSessionVerifierTest.java
index 01330c08c..0d32c80f2 100644
--- a/gateway-server/src/test/java/org/apache/knox/gateway/session/control/InMemoryConcurrentSessionVerifierTest.java
+++ b/gateway-server/src/test/java/org/apache/knox/gateway/session/control/InMemoryConcurrentSessionVerifierTest.java
@@ -62,13 +62,11 @@ public class InMemoryConcurrentSessionVerifierTest {
   private JWT adminToken3;
   private JWT adminToken4;
   private JWT adminToken5;
-  private JWT adminToken6;
   private JWT tomToken1;
   private JWT tomToken2;
   private JWT tomToken3;
   private JWT tomToken4;
   private JWT tomToken5;
-  private JWT tomToken6;
 
   @Before
   public void setUp() throws AliasServiceException, IOException, ServiceLifecycleException {
@@ -120,13 +118,11 @@ public class InMemoryConcurrentSessionVerifierTest {
       adminToken3 = tokenAuthority.issueToken(jwtAttributesForAdmin);
       adminToken4 = tokenAuthority.issueToken(jwtAttributesForAdmin);
       adminToken5 = tokenAuthority.issueToken(jwtAttributesForAdmin);
-      adminToken6 = tokenAuthority.issueToken(jwtAttributesForAdmin);
       tomToken1 = tokenAuthority.issueToken(jwtAttributesForTom);
       tomToken2 = tokenAuthority.issueToken(jwtAttributesForTom);
       tomToken3 = tokenAuthority.issueToken(jwtAttributesForTom);
       tomToken4 = tokenAuthority.issueToken(jwtAttributesForTom);
       tomToken5 = tokenAuthority.issueToken(jwtAttributesForTom);
-      tomToken6 = tokenAuthority.issueToken(jwtAttributesForTom);
     } catch (TokenServiceException ignored) {
     }
   }
@@ -164,10 +160,14 @@ public class InMemoryConcurrentSessionVerifierTest {
     GatewayConfig config = mockConfig(new HashSet<>(Arrays.asList("admin")), Collections.emptySet(), 3, 2);
     verifier.init(config, options);
 
-    Assert.assertTrue(verifier.verifySessionForUser("admin", adminToken1));
-    Assert.assertTrue(verifier.verifySessionForUser("admin", adminToken2));
-    Assert.assertTrue(verifier.verifySessionForUser("admin", adminToken3));
-    Assert.assertTrue(verifier.verifySessionForUser("admin", adminToken4));
+    Assert.assertTrue(verifier.verifySessionForUser("admin"));
+    Assert.assertTrue(verifier.registerToken("admin", adminToken1));
+    Assert.assertTrue(verifier.verifySessionForUser("admin"));
+    Assert.assertTrue(verifier.registerToken("admin", adminToken2));
+    Assert.assertTrue(verifier.verifySessionForUser("admin"));
+    Assert.assertTrue(verifier.registerToken("admin", adminToken3));
+    Assert.assertTrue(verifier.verifySessionForUser("admin"));
+    Assert.assertTrue(verifier.registerToken("admin", adminToken4));
   }
 
   @Test
@@ -175,13 +175,19 @@ public class InMemoryConcurrentSessionVerifierTest {
     GatewayConfig config = mockConfig(Collections.emptySet(), new HashSet<>(Arrays.asList("admin")), 3, 2);
     verifier.init(config, options);
 
-    Assert.assertTrue(verifier.verifySessionForUser("admin", adminToken1));
-    Assert.assertTrue(verifier.verifySessionForUser("admin", adminToken2));
-    Assert.assertTrue(verifier.verifySessionForUser("admin", adminToken3));
-    Assert.assertFalse(verifier.verifySessionForUser("admin", adminToken4));
+    Assert.assertTrue(verifier.verifySessionForUser("admin"));
+    Assert.assertTrue(verifier.registerToken("admin", adminToken1));
+    Assert.assertTrue(verifier.verifySessionForUser("admin"));
+    Assert.assertTrue(verifier.registerToken("admin", adminToken2));
+    Assert.assertTrue(verifier.verifySessionForUser("admin"));
+    Assert.assertTrue(verifier.registerToken("admin", adminToken3));
+    Assert.assertFalse(verifier.verifySessionForUser("admin"));
+    Assert.assertFalse(verifier.registerToken("admin", adminToken4));
     verifier.sessionEndedForUser("admin", adminToken1.toString());
-    Assert.assertTrue(verifier.verifySessionForUser("admin", adminToken5));
-    Assert.assertFalse(verifier.verifySessionForUser("admin", adminToken6));
+    Assert.assertTrue(verifier.verifySessionForUser("admin"));
+    Assert.assertTrue(verifier.registerToken("admin", adminToken5));
+    Assert.assertFalse(verifier.verifySessionForUser("admin"));
+    Assert.assertFalse(verifier.registerToken("admin", adminToken5));
   }
 
   @Test
@@ -189,21 +195,26 @@ public class InMemoryConcurrentSessionVerifierTest {
     GatewayConfig config = mockConfig(Collections.emptySet(), Collections.emptySet(), 3, 2);
     verifier.init(config, options);
 
-    Assert.assertTrue(verifier.verifySessionForUser("tom", tomToken1));
-    Assert.assertTrue(verifier.verifySessionForUser("tom", tomToken2));
-    Assert.assertFalse(verifier.verifySessionForUser("tom", tomToken3));
-    Assert.assertFalse(verifier.verifySessionForUser("tom", tomToken4));
+    Assert.assertTrue(verifier.verifySessionForUser("tom"));
+    Assert.assertTrue(verifier.registerToken("tom", tomToken1));
+    Assert.assertTrue(verifier.verifySessionForUser("tom"));
+    Assert.assertTrue(verifier.registerToken("tom", tomToken2));
+    Assert.assertFalse(verifier.verifySessionForUser("tom"));
+    Assert.assertFalse(verifier.registerToken("tom", tomToken3));
     verifier.sessionEndedForUser("tom", tomToken1.toString());
-    Assert.assertTrue(verifier.verifySessionForUser("tom", tomToken5));
-    Assert.assertFalse(verifier.verifySessionForUser("tom", tomToken6));
+    Assert.assertTrue(verifier.verifySessionForUser("tom"));
+    Assert.assertTrue(verifier.registerToken("tom", tomToken4));
+    Assert.assertFalse(verifier.verifySessionForUser("tom"));
+    Assert.assertFalse(verifier.registerToken("tom", tomToken5));
   }
 
   @Test
   public void testPrivilegedLimitIsZero() throws ServiceLifecycleException {
-    GatewayConfig config = mockConfig(Collections.emptySet(), new HashSet<>(Arrays.asList("tom")), 0, 2);
+    GatewayConfig config = mockConfig(Collections.emptySet(), new HashSet<>(Arrays.asList("admin")), 0, 2);
     verifier.init(config, options);
 
-    Assert.assertFalse(verifier.verifySessionForUser("tom", tomToken1));
+    Assert.assertFalse(verifier.verifySessionForUser("admin"));
+    Assert.assertFalse(verifier.registerToken("admin", adminToken1));
   }
 
   @Test
@@ -211,7 +222,8 @@ public class InMemoryConcurrentSessionVerifierTest {
     GatewayConfig config = mockConfig(Collections.emptySet(), Collections.emptySet(), 3, 0);
     verifier.init(config, options);
 
-    Assert.assertFalse(verifier.verifySessionForUser("tom", tomToken1));
+    Assert.assertFalse(verifier.verifySessionForUser("tom"));
+    Assert.assertFalse(verifier.registerToken("tom", tomToken1));
   }
 
   @Test
@@ -220,23 +232,23 @@ public class InMemoryConcurrentSessionVerifierTest {
     verifier.init(config, options);
 
     Assert.assertEquals(0, verifier.countValidTokensForUser("admin"));
-    verifier.verifySessionForUser("admin", adminToken1);
+    verifier.registerToken("admin", adminToken1);
     Assert.assertEquals(1, verifier.countValidTokensForUser("admin"));
     verifier.sessionEndedForUser("admin", adminToken1.toString());
     Assert.assertEquals(0, verifier.countValidTokensForUser("admin"));
     verifier.sessionEndedForUser("admin", adminToken1.toString());
     Assert.assertEquals(0, verifier.countValidTokensForUser("admin"));
-    verifier.verifySessionForUser("admin", adminToken2);
+    verifier.registerToken("admin", adminToken2);
     Assert.assertEquals(1, verifier.countValidTokensForUser("admin"));
 
     Assert.assertEquals(0, verifier.countValidTokensForUser("tom"));
-    verifier.verifySessionForUser("tom", tomToken1);
+    verifier.registerToken("tom", tomToken1);
     Assert.assertEquals(1, verifier.countValidTokensForUser("tom"));
     verifier.sessionEndedForUser("tom", tomToken1.toString());
     Assert.assertEquals(0, verifier.countValidTokensForUser("tom"));
     verifier.sessionEndedForUser("tom", tomToken1.toString());
     Assert.assertEquals(0, verifier.countValidTokensForUser("tom"));
-    verifier.verifySessionForUser("tom", tomToken2);
+    verifier.registerToken("tom", tomToken2);
     Assert.assertEquals(1, verifier.countValidTokensForUser("tom"));
   }
 
@@ -248,9 +260,11 @@ public class InMemoryConcurrentSessionVerifierTest {
     for (int i = 0; i < 10; i++) {
       try {
         JWT token = tokenAuthority.issueToken(jwtAttributesForAdmin);
-        Assert.assertTrue(verifier.verifySessionForUser("admin", token));
+        Assert.assertTrue(verifier.verifySessionForUser("admin"));
+        Assert.assertTrue(verifier.registerToken("admin", token));
         token = tokenAuthority.issueToken(jwtAttributesForTom);
-        Assert.assertTrue(verifier.verifySessionForUser("tom", token));
+        Assert.assertTrue(verifier.verifySessionForUser("tom"));
+        Assert.assertTrue(verifier.registerToken("tom", token));
       } catch (TokenServiceException ignored) {
       }
     }
@@ -261,22 +275,22 @@ public class InMemoryConcurrentSessionVerifierTest {
     GatewayConfig config = mockConfig(Collections.emptySet(), new HashSet<>(Arrays.asList("admin")), 3, 3);
     verifier.init(config, options);
 
-    verifier.verifySessionForUser("tom", tomToken1);
+    verifier.registerToken("tom", tomToken1);
     Assert.assertEquals(1, verifier.countValidTokensForUser("tom"));
     JWT expiredTomToken = tokenAuthority.issueToken(expiredJwtAttributesForTom);
-    verifier.verifySessionForUser("tom", expiredTomToken);
+    verifier.registerToken("tom", expiredTomToken);
     Assert.assertEquals(1, verifier.countValidTokensForUser("tom"));
     expiredTomToken = tokenAuthority.issueToken(expiredJwtAttributesForTom);
-    verifier.verifySessionForUser("tom", expiredTomToken);
+    verifier.registerToken("tom", expiredTomToken);
     Assert.assertEquals(1, verifier.countValidTokensForUser("tom"));
 
-    verifier.verifySessionForUser("admin", adminToken1);
+    verifier.registerToken("admin", adminToken1);
     Assert.assertEquals(1, verifier.countValidTokensForUser("admin"));
     JWT expiredAdminToken = tokenAuthority.issueToken(expiredJwtAttributesForAdmin);
-    verifier.verifySessionForUser("admin", expiredAdminToken);
+    verifier.registerToken("admin", expiredAdminToken);
     Assert.assertEquals(1, verifier.countValidTokensForUser("admin"));
     expiredAdminToken = tokenAuthority.issueToken(expiredJwtAttributesForAdmin);
-    verifier.verifySessionForUser("admin", expiredAdminToken);
+    verifier.registerToken("admin", expiredAdminToken);
     Assert.assertEquals(1, verifier.countValidTokensForUser("admin"));
   }
 
@@ -285,18 +299,18 @@ public class InMemoryConcurrentSessionVerifierTest {
     GatewayConfig config = mockConfig(Collections.emptySet(), new HashSet<>(Arrays.asList("admin")), 3, 3);
     verifier.init(config, options);
 
-    verifier.verifySessionForUser("admin", adminToken1);
-    verifier.verifySessionForUser("admin", adminToken2);
+    verifier.registerToken("admin", adminToken1);
+    verifier.registerToken("admin", adminToken2);
     JWT expiredAdminToken = tokenAuthority.issueToken(expiredJwtAttributesForAdmin);
-    verifier.verifySessionForUser("admin", expiredAdminToken);
+    verifier.registerToken("admin", expiredAdminToken);
     Assert.assertEquals(3, verifier.getTokenCountForUser("admin").intValue());
     verifier.removeExpiredTokens();
     Assert.assertEquals(2, verifier.getTokenCountForUser("admin").intValue());
 
-    verifier.verifySessionForUser("tom", tomToken1);
-    verifier.verifySessionForUser("tom", tomToken2);
+    verifier.registerToken("tom", tomToken1);
+    verifier.registerToken("tom", tomToken2);
     JWT expiredTomToken = tokenAuthority.issueToken(expiredJwtAttributesForTom);
-    verifier.verifySessionForUser("tom", expiredTomToken);
+    verifier.registerToken("tom", expiredTomToken);
     Assert.assertEquals(3, verifier.getTokenCountForUser("tom").intValue());
     verifier.removeExpiredTokens();
     Assert.assertEquals(2, verifier.getTokenCountForUser("tom").intValue());
@@ -321,7 +335,9 @@ public class InMemoryConcurrentSessionVerifierTest {
       } catch (InterruptedException | BrokenBarrierException | TokenServiceException e) {
         throw new RuntimeException(e);
       }
-      verifier.verifySessionForUser("admin", token);
+      if (verifier.verifySessionForUser("admin")) {
+        verifier.registerToken("admin", token);
+      }
     };
 
     for (int i = 0; i < 128; i++) {
@@ -386,7 +402,9 @@ public class InMemoryConcurrentSessionVerifierTest {
       } catch (InterruptedException | BrokenBarrierException | TokenServiceException e) {
         throw new RuntimeException(e);
       }
-      verifier.verifySessionForUser("tom", token);
+      if (verifier.verifySessionForUser("tom")) {
+        verifier.registerToken("tom", token);
+      }
     };
 
     for (int i = 0; i < 128; i++) {
diff --git a/gateway-service-knoxsso/src/main/java/org/apache/knox/gateway/service/knoxsso/WebSSOResource.java b/gateway-service-knoxsso/src/main/java/org/apache/knox/gateway/service/knoxsso/WebSSOResource.java
index 4aad6e942..39725129a 100644
--- a/gateway-service-knoxsso/src/main/java/org/apache/knox/gateway/service/knoxsso/WebSSOResource.java
+++ b/gateway-service-knoxsso/src/main/java/org/apache/knox/gateway/service/knoxsso/WebSSOResource.java
@@ -17,6 +17,10 @@
  */
 package org.apache.knox.gateway.service.knoxsso;
 
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static javax.ws.rs.core.MediaType.APPLICATION_XML;
+import static org.apache.knox.gateway.services.GatewayServices.GATEWAY_CLUSTER_ATTRIBUTE;
+
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
@@ -40,16 +44,16 @@ import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
-import javax.ws.rs.WebApplicationException;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.knox.gateway.audit.log4j.audit.Log4jAuditor;
 import org.apache.knox.gateway.config.GatewayConfig;
 import org.apache.knox.gateway.i18n.messages.MessagesFactory;
-import org.apache.knox.gateway.services.ServiceType;
 import org.apache.knox.gateway.services.GatewayServices;
+import org.apache.knox.gateway.services.ServiceType;
 import org.apache.knox.gateway.services.security.AliasService;
 import org.apache.knox.gateway.services.security.AliasServiceException;
 import org.apache.knox.gateway.services.security.token.JWTokenAttributes;
@@ -64,10 +68,6 @@ import org.apache.knox.gateway.util.RegExUtils;
 import org.apache.knox.gateway.util.Urls;
 import org.apache.knox.gateway.util.WhitelistUtils;
 
-import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
-import static javax.ws.rs.core.MediaType.APPLICATION_XML;
-import static org.apache.knox.gateway.services.GatewayServices.GATEWAY_CLUSTER_ATTRIBUTE;
-
 @Path( WebSSOResource.RESOURCE_PATH )
 public class WebSSOResource {
   private static final KnoxSSOMessages LOGGER = MessagesFactory.get( KnoxSSOMessages.class );
@@ -264,9 +264,14 @@ public class WebSSOResource {
       original = originalUrlCookies.get(0).getValue();
     }
 
+    Principal p = request.getUserPrincipal();
+    ConcurrentSessionVerifier verifier = services.getService(ServiceType.CONCURRENT_SESSION_VERIFIER);
+    if (!verifier.verifySessionForUser(p.getName())) {
+      throw new WebApplicationException("Too many sessions for user: " + request.getUserPrincipal().getName(), Response.Status.FORBIDDEN);
+    }
+
     AliasService as = services.getService(ServiceType.ALIAS_SERVICE);
     JWTokenAuthority tokenAuthority = services.getService(ServiceType.TOKEN_SERVICE);
-    Principal p = request.getUserPrincipal();
 
     try {
       String signingKeystoreName = context.getInitParameter(SSO_SIGNINGKEY_KEYSTORE_NAME);
@@ -291,8 +296,7 @@ public class WebSSOResource {
 
       // Coverity CID 1327959
       if (token != null) {
-        ConcurrentSessionVerifier verifier = services.getService(ServiceType.CONCURRENT_SESSION_VERIFIER);
-        if (!verifier.verifySessionForUser(p.getName(), token)) {
+        if (!verifier.registerToken(p.getName(), token)) {
           throw new WebApplicationException("Too many sessions for user: " + request.getUserPrincipal().getName(), Response.Status.FORBIDDEN);
         }
         addJWTHadoopCookie(original, token);
diff --git a/gateway-service-knoxsso/src/test/java/org/apache/knox/gateway/service/knoxsso/WebSSOResourceTest.java b/gateway-service-knoxsso/src/test/java/org/apache/knox/gateway/service/knoxsso/WebSSOResourceTest.java
index 126b4d119..d1d625429 100644
--- a/gateway-service-knoxsso/src/test/java/org/apache/knox/gateway/service/knoxsso/WebSSOResourceTest.java
+++ b/gateway-service-knoxsso/src/test/java/org/apache/knox/gateway/service/knoxsso/WebSSOResourceTest.java
@@ -185,7 +185,8 @@ public class WebSSOResourceTest {
     responseWrapper = new CookieResponseWrapper(response, outputStream);
 
     verifier = EasyMock.createNiceMock(ConcurrentSessionVerifier.class);
-    EasyMock.expect(verifier.verifySessionForUser(anyString(), anyObject())).andReturn(concurrentSessionVerifyResult).anyTimes();
+    EasyMock.expect(verifier.verifySessionForUser(anyString())).andReturn(concurrentSessionVerifyResult).anyTimes();
+    EasyMock.expect(verifier.registerToken(anyString(), anyObject())).andReturn(concurrentSessionVerifyResult).anyTimes();
     EasyMock.expect(services.getService(ServiceType.CONCURRENT_SESSION_VERIFIER)).andReturn(verifier).anyTimes();
 
     EasyMock.replay(principal, services, context, request, verifier);
@@ -555,7 +556,8 @@ public class WebSSOResourceTest {
     EasyMock.expect(aliasService.getPasswordFromAliasForGateway(TokenUtils.SIGNING_HMAC_SECRET_ALIAS)).andReturn(null).anyTimes();
 
     ConcurrentSessionVerifier concurrentSessionVerifier = EasyMock.createNiceMock(ConcurrentSessionVerifier.class);
-    EasyMock.expect(concurrentSessionVerifier.verifySessionForUser(anyString(), anyObject())).andReturn(true).anyTimes();
+    EasyMock.expect(concurrentSessionVerifier.verifySessionForUser(anyString())).andReturn(true).anyTimes();
+    EasyMock.expect(concurrentSessionVerifier.registerToken(anyString(), anyObject())).andReturn(true).anyTimes();
     EasyMock.expect(services.getService(ServiceType.CONCURRENT_SESSION_VERIFIER)).andReturn(concurrentSessionVerifier).anyTimes();
 
     JWTokenAuthority authority = new TestJWTokenAuthority(gatewayPublicKey, gatewayPrivateKey);
@@ -673,7 +675,8 @@ public class WebSSOResourceTest {
     EasyMock.expect(services.getService(ServiceType.ALIAS_SERVICE)).andReturn(aliasService).anyTimes();
 
     ConcurrentSessionVerifier concurrentSessionVerifier = EasyMock.createNiceMock(ConcurrentSessionVerifier.class);
-    EasyMock.expect(concurrentSessionVerifier.verifySessionForUser(anyString(), anyObject())).andReturn(true).anyTimes();
+    EasyMock.expect(concurrentSessionVerifier.verifySessionForUser(anyString())).andReturn(true).anyTimes();
+    EasyMock.expect(concurrentSessionVerifier.registerToken(anyString(), anyObject())).andReturn(true).anyTimes();
     EasyMock.expect(services.getService(ServiceType.CONCURRENT_SESSION_VERIFIER)).andReturn(concurrentSessionVerifier).anyTimes();
 
     HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/session/control/ConcurrentSessionVerifier.java b/gateway-spi/src/main/java/org/apache/knox/gateway/session/control/ConcurrentSessionVerifier.java
index f421f9c2c..a83e4b946 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/session/control/ConcurrentSessionVerifier.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/session/control/ConcurrentSessionVerifier.java
@@ -23,12 +23,23 @@ import org.apache.knox.gateway.services.security.token.impl.JWT;
 public interface ConcurrentSessionVerifier extends Service {
   /**
    * Verifies whether the given user is permitted to have a[nother] session or not.
+   * Similar to the registerToken function, but we need this in WebSSOResource to verify the before the token generation,
+   * so in case of an attack we are not wasting resources on token generation and storing.
    *
    * @param username the user who needs verification
-   * @param JWToken  the token which the user will use in the session
    * @return true if the user is allowed to have a[nother] session, false if the user is not allowed to have a[nother] session
    */
-  boolean verifySessionForUser(String username, JWT JWToken);
+  boolean verifySessionForUser(String username);
+
+  /**
+   * Verifies whether the given user is permitted to have a[nother] session or not.
+   * Also stores the token which the user is using for the session.
+   *
+   * @param jwtToken token which needs to be stored
+   * @param username the user who needs verification
+   * @return true if the user is allowed to have a[nother] session, false if the user is not allowed to have a[nother] session
+   */
+  boolean registerToken(String username, JWT jwtToken);
 
   void sessionEndedForUser(String username, String token);