From f96524a9f75e8e09ac80ed1b2553e9f5d71b0bb9 Mon Sep 17 00:00:00 2001 From: AmaliMatharaarachchi Date: Tue, 10 Oct 2023 15:51:28 +0530 Subject: [PATCH] token signature as key --- .../commons/dto/JWTValidationInfo.java | 9 +++++++ .../security/jwt/JWTAuthenticator.java | 26 +++++++++++++------ .../security/jwt/validator/JWTValidator.java | 3 ++- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/gateway/enforcer/org.wso2.apk.enforcer.commons/src/main/java/org/wso2/apk/enforcer/commons/dto/JWTValidationInfo.java b/gateway/enforcer/org.wso2.apk.enforcer.commons/src/main/java/org/wso2/apk/enforcer/commons/dto/JWTValidationInfo.java index 426ba868a9..dc8259a972 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer.commons/src/main/java/org/wso2/apk/enforcer/commons/dto/JWTValidationInfo.java +++ b/gateway/enforcer/org.wso2.apk.enforcer.commons/src/main/java/org/wso2/apk/enforcer/commons/dto/JWTValidationInfo.java @@ -41,6 +41,7 @@ public class JWTValidationInfo implements Serializable { private String keyManager; private String identifier; private JWTClaimsSet jwtClaimsSet; + private String token; public JWTValidationInfo() { @@ -58,6 +59,14 @@ public JWTValidationInfo(JWTValidationInfo jwtValidationInfo) { this.keyManager = jwtValidationInfo.getKeyManager(); } + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + public String getIdentifier() { return identifier; } diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/jwt/JWTAuthenticator.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/jwt/JWTAuthenticator.java index 28bf2267d9..114d763c4a 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/jwt/JWTAuthenticator.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/jwt/JWTAuthenticator.java @@ -464,11 +464,19 @@ private JSONObject validateSubscriptionFromClaim(String name, String version, JW */ private JWTValidationInfo getJwtValidationInfo(String jwtToken, String organization) throws APISecurityException { if (isGatewayTokenCacheEnabled) { + String[] jwtParts = jwtToken.split("\\."); + String signature = jwtParts[2]; Object validCacheToken = CacheProviderUtil.getOrganizationCache(organization).getGatewayKeyCache() - .getIfPresent(jwtToken); + .getIfPresent(signature); if (validCacheToken != null) { JWTValidationInfo validationInfo = (JWTValidationInfo) validCacheToken; if (!isJWTExpired(validationInfo)) { + if (!StringUtils.equals(validationInfo.getToken(), jwtToken)) { + log.warn("Suspected tampered token; a JWT token with the same signature is " + + "already available in the cache. Tampered token: " + FilterUtils.getMaskedToken(jwtToken)); + throw new APISecurityException(APIConstants.StatusCodes.UNAUTHENTICATED.getCode(), + APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, "Invalid JWT token"); + } if (RevokedJWTDataHolder.isJWTTokenSignatureExistsInRevokedMap(validationInfo.getIdentifier())) { log.debug("Token found in the revoked jwt token map."); throw new APISecurityException(APIConstants.StatusCodes.UNAUTHENTICATED.getCode(), @@ -476,14 +484,14 @@ private JWTValidationInfo getJwtValidationInfo(String jwtToken, String organizat } return validationInfo; } else { - CacheProviderUtil.getOrganizationCache(organization).getGatewayKeyCache().invalidate(jwtToken); - CacheProviderUtil.getOrganizationCache(organization).getInvalidTokenCache().put(jwtToken, true); + CacheProviderUtil.getOrganizationCache(organization).getGatewayKeyCache().invalidate(signature); + CacheProviderUtil.getOrganizationCache(organization).getInvalidTokenCache().put(signature, true); throw new APISecurityException(APIConstants.StatusCodes.UNAUTHENTICATED.getCode(), APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE); } } else if (CacheProviderUtil.getOrganizationCache(organization).getInvalidTokenCache() - .getIfPresent(jwtToken) != null) { + .getIfPresent(signature) != null) { throw new APISecurityException(APIConstants.StatusCodes.UNAUTHENTICATED.getCode(), APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE); @@ -519,8 +527,9 @@ private JWTValidationInfo getJwtValidationInfo(String jwtToken, String organizat } } + String signature = signedJWT.getSignature().toString(); String jwtTokenIdentifier = StringUtils.isNotEmpty(jwtClaimsSet.getJWTID()) ? jwtClaimsSet.getJWTID() : - signedJWT.getSignature().toString(); + signature; // check whether the token is revoked String jwtHeader = signedJWT.getHeader().toString(); @@ -543,13 +552,14 @@ private JWTValidationInfo getJwtValidationInfo(String jwtToken, String organizat APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE); } - JWTValidationInfo jwtValidationInfo = jwtValidator.validateToken(signedJWTInfo); + JWTValidationInfo jwtValidationInfo = jwtValidator.validateToken(jwtToken, signedJWTInfo); if (isGatewayTokenCacheEnabled) { // Add token to tenant token cache if (jwtValidationInfo.isValid()) { - CacheProviderUtil.getOrganizationCache(organization).getGatewayKeyCache().put(jwtToken, jwtValidationInfo); + CacheProviderUtil.getOrganizationCache(organization).getGatewayKeyCache().put(signature, + jwtValidationInfo); } else { - CacheProviderUtil.getOrganizationCache(organization).getInvalidTokenCache().put(jwtToken, true); + CacheProviderUtil.getOrganizationCache(organization).getInvalidTokenCache().put(signature, true); } } return jwtValidationInfo; diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/jwt/validator/JWTValidator.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/jwt/validator/JWTValidator.java index 75cba53493..1813c99977 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/jwt/validator/JWTValidator.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/jwt/validator/JWTValidator.java @@ -75,7 +75,7 @@ public JWTValidator(ExtendedTokenIssuerDto tokenIssuer) throws EnforcerException } } - public JWTValidationInfo validateToken(SignedJWTInfo signedJWTInfo) throws EnforcerException { + public JWTValidationInfo validateToken(String token, SignedJWTInfo signedJWTInfo) throws EnforcerException { JWTValidationInfo jwtValidationInfo = new JWTValidationInfo(); boolean state; try { @@ -91,6 +91,7 @@ public JWTValidationInfo validateToken(SignedJWTInfo signedJWTInfo) throws Enfor jwtValidationInfo.setKeyManager(tokenIssuer.getName()); jwtValidationInfo.setIdentifier(JWTUtils.getJWTTokenIdentifier(signedJWTInfo)); jwtValidationInfo.setJwtClaimsSet(signedJWTInfo.getJwtClaimsSet()); + jwtValidationInfo.setToken(token); return jwtValidationInfo; } logger.debug("Token is expired.");