From b988cb284215a4f24d7ab7934efc29e4231a6ae9 Mon Sep 17 00:00:00 2001 From: GihanAyesh Date: Thu, 13 Jul 2023 17:32:17 +0530 Subject: [PATCH 1/3] Add apim.jwt.decoding property to api-manager.xml.j2 --- .../apimgt/common/gateway/dto/JWTConfigurationDto.java | 10 ++++++++++ .../java/org/wso2/carbon/apimgt/impl/APIConstants.java | 1 + .../carbon/apimgt/impl/APIManagerConfiguration.java | 5 +++++ .../templates/repository/conf/api-manager.xml.j2 | 8 ++++++++ 4 files changed, 24 insertions(+) diff --git a/components/apimgt/org.wso2.carbon.apimgt.common.gateway/src/main/java/org/wso2/carbon/apimgt/common/gateway/dto/JWTConfigurationDto.java b/components/apimgt/org.wso2.carbon.apimgt.common.gateway/src/main/java/org/wso2/carbon/apimgt/common/gateway/dto/JWTConfigurationDto.java index ef034354fede..6991c61e30d9 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.common.gateway/src/main/java/org/wso2/carbon/apimgt/common/gateway/dto/JWTConfigurationDto.java +++ b/components/apimgt/org.wso2.carbon.apimgt.common.gateway/src/main/java/org/wso2/carbon/apimgt/common/gateway/dto/JWTConfigurationDto.java @@ -34,6 +34,7 @@ public class JWTConfigurationDto { private String jwtHeader = "X-JWT-Assertion"; private String consumerDialectUri = "http://wso2.org/claims"; private String signatureAlgorithm = "SHA256withRSA"; + private String jwtDecoding = "base64"; private boolean enableUserClaims; private String gatewayJWTGeneratorImpl; private Map tokenIssuerDtoMap = new HashMap(); @@ -58,6 +59,7 @@ public JWTConfigurationDto(JWTConfigurationDto jwtConfigurationDto) { this.jwtHeader = jwtConfigurationDto.jwtHeader; this.consumerDialectUri = jwtConfigurationDto.consumerDialectUri; this.signatureAlgorithm = jwtConfigurationDto.signatureAlgorithm; + this.jwtDecoding = jwtConfigurationDto.jwtDecoding; this.enableUserClaims = jwtConfigurationDto.enableUserClaims; this.gatewayJWTGeneratorImpl = jwtConfigurationDto.gatewayJWTGeneratorImpl; this.tokenIssuerDtoMap = jwtConfigurationDto.tokenIssuerDtoMap; @@ -140,6 +142,14 @@ public void setJwtExcludedClaims(Set jwtClaims) { this.jwtExcludedClaims = jwtClaims; } + public String getJwtDecoding() { + return jwtDecoding; + } + + public void setJwtDecoding(String jwtDecoding) { + this.jwtDecoding = jwtDecoding; + } + public boolean isEnableUserClaims() { return enableUserClaims; diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java index a6a33062ac1b..00179b6a1781 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java @@ -439,6 +439,7 @@ public final class APIConstants { public static final String JWT_DEFAULT_AUDIENCE = "http://org.wso2.apimgt/gateway"; public static final String JWT_CONFIGS = "JWTConfiguration"; public static final String JWT_HEADER = "JWTHeader"; + public static final String JWT_DECODING = "JWTDecoding"; public static final String ENABLE_USER_CLAIMS = "EnableUserClaims"; public static final String BINDING_FEDERATED_USER_CLAIMS = "EnableBindingFederatedUserClaims"; public static final String TOKEN_GENERATOR_IMPL = "JWTGeneratorImpl"; diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIManagerConfiguration.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIManagerConfiguration.java index 766988fdd961..0fe3377b76f7 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIManagerConfiguration.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIManagerConfiguration.java @@ -1603,6 +1603,11 @@ private void setJWTConfiguration(OMElement omElement) { if (jwtHeaderElement != null) { jwtConfigurationDto.setJwtHeader(jwtHeaderElement.getText()); } + OMElement jwtDecoding = + omElement.getFirstChildWithName(new QName(APIConstants.JWT_DECODING)); + if (jwtDecoding != null) { + jwtConfigurationDto.setJwtDecoding(jwtDecoding.getText()); + } OMElement jwtUserClaimsElement = omElement.getFirstChildWithName(new QName(APIConstants.ENABLE_USER_CLAIMS)); if (jwtUserClaimsElement != null) { diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/conf_templates/templates/repository/conf/api-manager.xml.j2 b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/conf_templates/templates/repository/conf/api-manager.xml.j2 index 54eac0d02d5c..4d09c2102bfc 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/conf_templates/templates/repository/conf/api-manager.xml.j2 +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/conf_templates/templates/repository/conf/api-manager.xml.j2 @@ -75,6 +75,14 @@ + + + {% if apim.jwt.decoding %} + {{apim.jwt.decoding}} + {% elif apim.jwt.encoding %} + {{apim.jwt.encoding}} + {% endif %} + {% if apim.jwt.enable_tenant_based_signing is defined %} {{apim.jwt.enable_tenant_based_signing}} {% endif %} From 6a3ac8ee1a8a814ecbba689c655530341e817f02 Mon Sep 17 00:00:00 2001 From: GihanAyesh Date: Thu, 13 Jul 2023 17:32:31 +0530 Subject: [PATCH 2/3] logic to handle both base64url and base64 --- .../handlers/security/apikey/ApiKeyAuthenticator.java | 7 ++++++- .../apimgt/gateway/handlers/security/jwt/JWTValidator.java | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/apikey/ApiKeyAuthenticator.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/apikey/ApiKeyAuthenticator.java index f5886d7884aa..6445d766a9cb 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/apikey/ApiKeyAuthenticator.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/apikey/ApiKeyAuthenticator.java @@ -515,7 +515,12 @@ private String generateAndRetrieveBackendJWTToken(String tokenSignature, JWTInfo if (token != null) { endUserToken = (String) token; String[] splitToken = ((String) token).split("\\."); - JSONObject payload = new JSONObject(new String(Base64.getUrlDecoder().decode(splitToken[1]))); + JSONObject payload; + if (jwtConfigurationDto.getJwtDecoding().equals("base64url")) { + payload = new JSONObject(new String(Base64.getUrlDecoder().decode(splitToken[1]))); + } else { + payload = new JSONObject(new String(Base64.getDecoder().decode(splitToken[1]))); + } long exp = payload.getLong("exp"); long timestampSkew = OAuthServerConfiguration.getInstance().getTimeStampSkewInSeconds() * 1000; valid = (exp - System.currentTimeMillis() > timestampSkew); diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/jwt/JWTValidator.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/jwt/JWTValidator.java index 7e418f7e0771..f242c9087984 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/jwt/JWTValidator.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/jwt/JWTValidator.java @@ -290,7 +290,12 @@ private String generateAndRetrieveJWTToken(String tokenSignature, JWTInfoDto jwt if (token != null) { endUserToken = (String) token; String[] splitToken = ((String) token).split("\\."); - JSONObject payload = new JSONObject(new String(Base64.getUrlDecoder().decode(splitToken[1]))); + JSONObject payload; + if (jwtConfigurationDto.getJwtDecoding().equals("base64url")) { + payload = new JSONObject(new String(Base64.getUrlDecoder().decode(splitToken[1]))); + } else { + payload = new JSONObject(new String(Base64.getDecoder().decode(splitToken[1]))); + } long exp = payload.getLong("exp") * 1000L; long timestampSkew = getTimeStampSkewInSeconds() * 1000; valid = (exp - System.currentTimeMillis() > timestampSkew); From 7563d0924c2f3afc46c3e928b26cf0e990d560e1 Mon Sep 17 00:00:00 2001 From: GihanAyesh Date: Tue, 18 Jul 2023 09:43:24 +0530 Subject: [PATCH 3/3] Refactoring variables --- .../gateway/handlers/security/apikey/ApiKeyAuthenticator.java | 2 +- .../apimgt/gateway/handlers/security/jwt/JWTValidator.java | 2 +- .../src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/apikey/ApiKeyAuthenticator.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/apikey/ApiKeyAuthenticator.java index 6445d766a9cb..83732353ffd4 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/apikey/ApiKeyAuthenticator.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/apikey/ApiKeyAuthenticator.java @@ -516,7 +516,7 @@ private String generateAndRetrieveBackendJWTToken(String tokenSignature, JWTInfo endUserToken = (String) token; String[] splitToken = ((String) token).split("\\."); JSONObject payload; - if (jwtConfigurationDto.getJwtDecoding().equals("base64url")) { + if (APIConstants.JwtTokenConstants.DECODING_ALGORITHM_BASE64URL.equals(jwtConfigurationDto.getJwtDecoding())) { payload = new JSONObject(new String(Base64.getUrlDecoder().decode(splitToken[1]))); } else { payload = new JSONObject(new String(Base64.getDecoder().decode(splitToken[1]))); diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/jwt/JWTValidator.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/jwt/JWTValidator.java index f242c9087984..4116e0bc2c1a 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/jwt/JWTValidator.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/jwt/JWTValidator.java @@ -291,7 +291,7 @@ private String generateAndRetrieveJWTToken(String tokenSignature, JWTInfoDto jwt endUserToken = (String) token; String[] splitToken = ((String) token).split("\\."); JSONObject payload; - if (jwtConfigurationDto.getJwtDecoding().equals("base64url")) { + if (APIConstants.JwtTokenConstants.DECODING_ALGORITHM_BASE64URL.equals(jwtConfigurationDto.getJwtDecoding())) { payload = new JSONObject(new String(Base64.getUrlDecoder().decode(splitToken[1]))); } else { payload = new JSONObject(new String(Base64.getDecoder().decode(splitToken[1]))); diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java index 00179b6a1781..73838d29ee13 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java @@ -2101,6 +2101,7 @@ public static class JwtTokenConstants { public static final String INTERNAL_KEY_TOKEN_TYPE = "InternalKey"; public static final String TOKEN_TYPE = "token_type"; public static final String API_KEY_TOKEN_TYPE = "apiKey"; + public static final String DECODING_ALGORITHM_BASE64URL = "base64url"; } public static final String SIGNATURE_ALGORITHM_RS256 = "RS256";