diff --git a/security/src/main/java/com/networknt/security/JwtVerifier.java b/security/src/main/java/com/networknt/security/JwtVerifier.java index 64a2d70b95..00eb7d3730 100644 --- a/security/src/main/java/com/networknt/security/JwtVerifier.java +++ b/security/src/main/java/com/networknt/security/JwtVerifier.java @@ -303,6 +303,9 @@ public JwtClaims verifyJwt(String jwt, boolean ignoreExpiry, boolean isToken, St claims = jwtContext.getJwtClaims(); if (Boolean.TRUE.equals(enableJwtCache)) { cache.put(jwt, claims); + if(cache.estimatedSize() > config.getJwtCacheFullSize()) { + logger.error("JWT cache exceeds the size limit " + config.getJwtCacheFullSize()); + } } return claims; } diff --git a/security/src/main/java/com/networknt/security/SecurityConfig.java b/security/src/main/java/com/networknt/security/SecurityConfig.java index 41266772f9..740dd2c8c4 100644 --- a/security/src/main/java/com/networknt/security/SecurityConfig.java +++ b/security/src/main/java/com/networknt/security/SecurityConfig.java @@ -32,6 +32,7 @@ public class SecurityConfig { private static final String LOG_JWT_TOKEN = "logJwtToken"; private static final String LOG_CLIENT_USER_SCOPE = "logClientUserScope"; private static final String ENABLE_JWT_CACHE = "enableJwtCache"; + private static final String JWT_CACHE_FULL_SIZE = "jwtCacheFullSize"; private static final String BOOTSTRAP_FROM_KEY_SERVICE = "bootstrapFromKeyService"; private static final String IGNORE_JWT_EXPIRY = "ignoreJwtExpiry"; private static final String PROVIDER_ID = "providerId"; @@ -53,6 +54,7 @@ public class SecurityConfig { private boolean logJwtToken; private boolean logClientUserScope; private boolean enableJwtCache; + private int jwtCacheFullSize; private boolean bootstrapFromKeyService; private boolean ignoreJwtExpiry; private String providerId; @@ -132,6 +134,9 @@ public boolean isEnableJwtCache() { return enableJwtCache; } + public int getJwtCacheFullSize() { + return jwtCacheFullSize; + } public boolean isBootstrapFromKeyService() { return bootstrapFromKeyService; } @@ -212,6 +217,10 @@ private void setConfigData() { if(object != null && (Boolean) object) { enableJwtCache = true; } + object = getMappedConfig().get(JWT_CACHE_FULL_SIZE); + if(object != null ) { + jwtCacheFullSize = (Integer)object; + } object = getMappedConfig().get(BOOTSTRAP_FROM_KEY_SERVICE); if(object != null && (Boolean) object) { bootstrapFromKeyService = true; diff --git a/security/src/main/resources/config/security.yml b/security/src/main/resources/config/security.yml index 112e9362b0..8efcffdf50 100644 --- a/security/src/main/resources/config/security.yml +++ b/security/src/main/resources/config/security.yml @@ -48,9 +48,20 @@ logJwtToken: ${security.logJwtToken:true} logClientUserScope: ${security.logClientUserScope:false} # Enable JWT token cache to speed up verification. This will only verify expired time -# and skip the signature verification as it takes more CPU power and long time. +# and skip the signature verification as it takes more CPU power and a long time. If +# each request has a different jwt token, like authorization code flow, this indicator +# should be turned off. Otherwise, the cached jwt will only be removed after 15 minutes +# and the cache can grow bigger if the number of requests is very high. This will cause +# memory kill in a Kubernetes pod if the memory setting is limited. enableJwtCache: ${security.enableJwtCache:true} +# If enableJwtCache is true, then an error message will be shown up in the log if the +# cache size is bigger than the jwtCacheFullSize. This helps the developers to detect +# cache problem if many distinct tokens flood the cache in a short period of time. If +# you see JWT cache exceeds the size limit in logs, you need to turn off the enableJwtCache +# or increase the cache full size to a bigger number from the default 100. +jwtCacheFullSize: ${security.jwtCacheFullSize:100} + # If you are using light-oauth2, then you don't need to have oauth subfolder for public # key certificate to verify JWT token, the key will be retrieved from key endpoint once # the first token is arrived. Default to false for dev environment without oauth2 server diff --git a/security/src/test/resources/config/openapi-security-no-default-jwtcertificate.yml b/security/src/test/resources/config/openapi-security-no-default-jwtcertificate.yml index 6ce064e03e..7cc486fe98 100644 --- a/security/src/test/resources/config/openapi-security-no-default-jwtcertificate.yml +++ b/security/src/test/resources/config/openapi-security-no-default-jwtcertificate.yml @@ -23,9 +23,20 @@ logJwtToken: ${openapi-security.logJwtToken:true} logClientUserScope: ${openapi-security.logClientUserScope:false} # Enable JWT token cache to speed up verification. This will only verify expired time -# and skip the signature verification as it takes more CPU power and long time. +# and skip the signature verification as it takes more CPU power and a long time. If +# each request has a different jwt token, like authorization code flow, this indicator +# should be turned off. Otherwise, the cached jwt will only be removed after 15 minutes +# and the cache can grow bigger if the number of requests is very high. This will cause +# memory kill in a Kubernetes pod if the memory setting is limited. enableJwtCache: ${openapi-security.enableJwtCache:true} +# If enableJwtCache is true, then an error message will be shown up in the log if the +# cache size is bigger than the jwtCacheFullSize. This helps the developers to detect +# cache problem if many distinct tokens flood the cache in a short period of time. If +# you see JWT cache exceeds the size limit in logs, you need to turn off the enableJwtCache +# or increase the cache full size to a bigger number from the default 100. +jwtCacheFullSize: ${openapi-security.jwtCacheFullSize:100} + # If you are using light-oauth2, then you don't need to have oauth subfolder for public # key certificate to verify JWT token, the key will be retrieved from key endpoint once # the first token is arrived. Default to false for dev environment without oauth2 server diff --git a/security/src/test/resources/config/security-509.yml b/security/src/test/resources/config/security-509.yml index ff8a92fa71..18adbdb7ac 100644 --- a/security/src/test/resources/config/security-509.yml +++ b/security/src/test/resources/config/security-509.yml @@ -41,9 +41,20 @@ logJwtToken: true logClientUserScope: false # Enable JWT token cache to speed up verification. This will only verify expired time -# and skip the signature verification as it takes more CPU power and long time. +# and skip the signature verification as it takes more CPU power and long time. If +# each request has a different jwt token like authorization code flow, this indicator +# should be turned off. Otherwise, the cached jwt will only be removed after 15 minutes +# and the cache can grow bigger if the number of the requests are very high. This will +# cause memory kill in a Kubernetes pod if the memory setting is limited. enableJwtCache: true +# If enableJwtCache is true, then an error message will be shown up in the log if the +# cache size is bigger than the jwtCacheFullSize. This helps the developers to detect +# cache problem if many distinct tokens flood the cache in a short period time. If you +# see JWT cache exceeds size limit in logs, you need to turn off the enableJwtCache or +# increase the cache full size to a bigger number from the default 100. +jwtCacheFullSize: 100 + # If you are using light-oauth2, then you don't need to have oauth subfolder for public # key certificate to verify JWT token, the key will be retrieved from key endpoint once # the first token is arrived. Default to false for dev environment without oauth2 server diff --git a/security/src/test/resources/config/security-relaxedVerification.yml b/security/src/test/resources/config/security-relaxedVerification.yml index 564c671e37..db6c25cc1f 100644 --- a/security/src/test/resources/config/security-relaxedVerification.yml +++ b/security/src/test/resources/config/security-relaxedVerification.yml @@ -40,9 +40,20 @@ logJwtToken: true logClientUserScope: false # Enable JWT token cache to speed up verification. This will only verify expired time -# and skip the signature verification as it takes more CPU power and long time. +# and skip the signature verification as it takes more CPU power and long time. If +# each request has a different jwt token like authorization code flow, this indicator +# should be turned off. Otherwise, the cached jwt will only be removed after 15 minutes +# and the cache can grow bigger if the number of the requests are very high. This will +# cause memory kill in a Kubernetes pod if the memory setting is limited. enableJwtCache: true +# If enableJwtCache is true, then an error message will be shown up in the log if the +# cache size is bigger than the jwtCacheFullSize. This helps the developers to detect +# cache problem if many distinct tokens flood the cache in a short period time. If you +# see JWT cache exceeds size limit in logs, you need to turn off the enableJwtCache or +# increase the cache full size to a bigger number from the default 100. +jwtCacheFullSize: 100 + # If you are using light-oauth2, then you don't need to have oauth subfolder for public # key certificate to verify JWT token, the key will be retrieved from key endpoint once # the first token is arrived. Default to false for dev environment without oauth2 server diff --git a/security/src/test/resources/config/security-template.yml b/security/src/test/resources/config/security-template.yml index 65d035b873..43919a5d61 100644 --- a/security/src/test/resources/config/security-template.yml +++ b/security/src/test/resources/config/security-template.yml @@ -48,9 +48,20 @@ logJwtToken: ${security.logJwtToken:true} logClientUserScope: ${security.logClientUserScope:false} # Enable JWT token cache to speed up verification. This will only verify expired time -# and skip the signature verification as it takes more CPU power and long time. +# and skip the signature verification as it takes more CPU power and a long time. If +# each request has a different jwt token, like authorization code flow, this indicator +# should be turned off. Otherwise, the cached jwt will only be removed after 15 minutes +# and the cache can grow bigger if the number of requests is very high. This will cause +# memory kill in a Kubernetes pod if the memory setting is limited. enableJwtCache: ${security.enableJwtCache:true} +# If enableJwtCache is true, then an error message will be shown up in the log if the +# cache size is bigger than the jwtCacheFullSize. This helps the developers to detect +# cache problem if many distinct tokens flood the cache in a short period of time. If +# you see JWT cache exceeds the size limit in logs, you need to turn off the enableJwtCache +# or increase the cache full size to a bigger number from the default 100. +jwtCacheFullSize: ${security.jwtCacheFullSize:100} + # If you are using light-oauth2, then you don't need to have oauth subfolder for public # key certificate to verify JWT token, the key will be retrieved from key endpoint once # the first token is arrived. Default to false for dev environment without oauth2 server diff --git a/security/src/test/resources/config/security.yml b/security/src/test/resources/config/security.yml index 28212d7c8c..3f0cb845e4 100644 --- a/security/src/test/resources/config/security.yml +++ b/security/src/test/resources/config/security.yml @@ -41,9 +41,20 @@ logJwtToken: true logClientUserScope: false # Enable JWT token cache to speed up verification. This will only verify expired time -# and skip the signature verification as it takes more CPU power and long time. +# and skip the signature verification as it takes more CPU power and long time. If +# each request has a different jwt token like authorization code flow, this indicator +# should be turned off. Otherwise, the cached jwt will only be removed after 15 minutes +# and the cache can grow bigger if the number of the requests are very high. This will +# cause memory kill in a Kubernetes pod if the memory setting is limited. enableJwtCache: true +# If enableJwtCache is true, then an error message will be shown up in the log if the +# cache size is bigger than the jwtCacheFullSize. This helps the developers to detect +# cache problem if many distinct tokens flood the cache in a short period time. If you +# see JWT cache exceeds size limit in logs, you need to turn off the enableJwtCache or +# increase the cache full size to a bigger number from the default 100. +jwtCacheFullSize: 100 + # If you are using light-oauth2, then you don't need to have oauth subfolder for public # key certificate to verify JWT token, the key will be retrieved from key endpoint once # the first token is arrived. Default to false for dev environment without oauth2 server