From e8c124d8ec4ea9e9d346e87386c35896a7fc9742 Mon Sep 17 00:00:00 2001 From: Zihlu Wang Date: Thu, 25 Jan 2024 23:34:20 +0800 Subject: [PATCH] fix: Fix the issue that reports illegal base64 character when decoding a JWT Payload --- .../codecrafters/devkit/utils/Base64Util.java | 64 +++++++++++++++++++ .../authzero/AuthzeroTokenResolver.java | 4 +- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/devkit-utils/src/main/java/cn/org/codecrafters/devkit/utils/Base64Util.java b/devkit-utils/src/main/java/cn/org/codecrafters/devkit/utils/Base64Util.java index 309b83c..0f38bc6 100644 --- a/devkit-utils/src/main/java/cn/org/codecrafters/devkit/utils/Base64Util.java +++ b/devkit-utils/src/main/java/cn/org/codecrafters/devkit/utils/Base64Util.java @@ -60,6 +60,10 @@ public final class Base64Util { private static Base64.Decoder decoder; + private static Base64.Encoder urlEncoder; + + private static Base64.Decoder urlDecoder; + /** * Ensure that there is only one Base64 Encoder. * @@ -84,6 +88,20 @@ public final class Base64Util { return decoder; } + private static Base64.Encoder getUrlEncoder() { + if (Objects.isNull(urlEncoder)) { + urlEncoder = Base64.getUrlEncoder(); + } + return urlEncoder; + } + + public static Base64.Decoder getUrlDecoder() { + if (Objects.isNull(urlDecoder)) { + urlDecoder = Base64.getUrlDecoder(); + } + return urlDecoder; + } + /** * Private constructor to prevent instantiation of the class. */ @@ -136,4 +154,50 @@ public final class Base64Util { return decode(value, StandardCharsets.UTF_8); } + /** + * Encodes the given string using the specified charset. + * + * @param value the string to be encoded + * @param charset the charset to be used for encoding + * @return the Base64 encoded string + */ + public static String encodeUrlComponents(String value, Charset charset) { + var encoded = getUrlEncoder().encode(value.getBytes(charset)); + + return new String(encoded); + } + + /** + * Encodes the given string using the default UTF-8 charset. + * + * @param value the string to be encoded + * @return the Base64 encoded string + */ + public static String encodeUrlComponents(String value) { + return encodeUrlComponents(value, StandardCharsets.UTF_8); + } + + /** + * Decodes the given Base64 encoded string using the specified charset. + * + * @param value the Base64 encoded string to be decoded + * @param charset the charset to be used for decoding + * @return the decoded string + */ + public static String decodeUrlComponents(String value, Charset charset) { + var decoded = getUrlDecoder().decode(value.getBytes(charset)); + + return new String(decoded); + } + + /** + * Decodes the given Base64 encoded string using the default UTF-8 charset. + * + * @param value the Base64 encoded string to be decoded + * @return the decoded string + */ + public static String decodeUrlComponents(String value) { + return decodeUrlComponents(value, StandardCharsets.UTF_8); + } + } \ No newline at end of file diff --git a/simple-jwt-authzero/src/main/java/cn/org/codecrafters/simplejwt/authzero/AuthzeroTokenResolver.java b/simple-jwt-authzero/src/main/java/cn/org/codecrafters/simplejwt/authzero/AuthzeroTokenResolver.java index e60e1d4..80d3eaa 100644 --- a/simple-jwt-authzero/src/main/java/cn/org/codecrafters/simplejwt/authzero/AuthzeroTokenResolver.java +++ b/simple-jwt-authzero/src/main/java/cn/org/codecrafters/simplejwt/authzero/AuthzeroTokenResolver.java @@ -429,7 +429,7 @@ public class AuthzeroTokenResolver implements TokenResolver { public T extract(String token, Class targetType) { try { // Get claims from token. - var payloads = objectMapper.readValue(Base64Util.decode(resolve(token).getPayload()), new MapTypeReference()); + var payloads = objectMapper.readValue(Base64Util.decodeUrlComponents(resolve(token).getPayload()), new MapTypeReference()); // Get the no-argument constructor to create an instance. var bean = targetType.getConstructor().newInstance(); @@ -478,7 +478,7 @@ public class AuthzeroTokenResolver implements TokenResolver { var resolved = resolve(oldToken); try { - var payload = objectMapper.readValue(Base64Util.decode(resolved.getPayload()), ObjectNode.class); + var payload = objectMapper.readValue(Base64Util.decodeUrlComponents(resolved.getPayload()), ObjectNode.class); payload.remove(PredefinedKeys.KEYS); var payloadMap = objectMapper.convertValue(payload, new MapTypeReference());