diff --git a/tests/src/test/java/io/scalecube/security/tokens/jwt/JsonwebtokenResolverTests.java b/tests/src/test/java/io/scalecube/security/tokens/jwt/JsonwebtokenResolverTests.java index d1eb992..bc9e8de 100644 --- a/tests/src/test/java/io/scalecube/security/tokens/jwt/JsonwebtokenResolverTests.java +++ b/tests/src/test/java/io/scalecube/security/tokens/jwt/JsonwebtokenResolverTests.java @@ -24,7 +24,7 @@ public class JsonwebtokenResolverTests { @Test - void testResolveTokenSuccessfully(VaultEnvironment vaultEnvironment) throws Exception { + void testResolveTokenTokenSuccessfully(VaultEnvironment vaultEnvironment) throws Exception { final var token = vaultEnvironment.newServiceToken(); final var jwtToken = @@ -35,7 +35,7 @@ void testResolveTokenSuccessfully(VaultEnvironment vaultEnvironment) throws Exce .requestTimeout(Duration.ofSeconds(3)) .keyTtl(1000) .build()) - .resolve(token) + .resolveToken(token) .get(3, TimeUnit.SECONDS); assertNotNull(jwtToken, "jwtToken"); @@ -47,15 +47,7 @@ void testResolveTokenSuccessfully(VaultEnvironment vaultEnvironment) throws Exce void testParseTokenSuccessfully(VaultEnvironment vaultEnvironment) { final var token = vaultEnvironment.newServiceToken(); - final var jwtToken = - new JsonwebtokenResolver( - JwksKeyLocator.builder() - .jwksUri(vaultEnvironment.jwksUri()) - .connectTimeout(Duration.ofSeconds(3)) - .requestTimeout(Duration.ofSeconds(3)) - .keyTtl(1000) - .build()) - .parse(token); + final var jwtToken = JwtToken.parseToken(token); assertNotNull(jwtToken, "jwtToken"); assertTrue(jwtToken.header().size() > 0, "jwtToken.header: " + jwtToken.header()); @@ -70,7 +62,7 @@ void testJwksKeyLocatorThrowsError(VaultEnvironment vaultEnvironment) { when(keyLocator.locate(any())).thenThrow(new RuntimeException("Cannot get key")); try { - new JsonwebtokenResolver(keyLocator).resolve(token).get(3, TimeUnit.SECONDS); + new JsonwebtokenResolver(keyLocator).resolveToken(token).get(3, TimeUnit.SECONDS); fail("Expected exception"); } catch (Exception e) { final var ex = getRootCause(e); @@ -87,7 +79,7 @@ void testJwksKeyLocatorThrowsRetryableError(VaultEnvironment vaultEnvironment) { when(keyLocator.locate(any())).thenThrow(new JwtUnavailableException("JWKS timeout")); try { - new JsonwebtokenResolver(keyLocator).resolve(token).get(3, TimeUnit.SECONDS); + new JsonwebtokenResolver(keyLocator).resolveToken(token).get(3, TimeUnit.SECONDS); fail("Expected exception"); } catch (Exception e) { final var ex = getRootCause(e); diff --git a/tests/src/test/java/io/scalecube/security/vault/VaultServiceTokenTests.java b/tests/src/test/java/io/scalecube/security/vault/VaultServiceTokenTests.java index fb09fb5..80f3430 100644 --- a/tests/src/test/java/io/scalecube/security/vault/VaultServiceTokenTests.java +++ b/tests/src/test/java/io/scalecube/security/vault/VaultServiceTokenTests.java @@ -143,7 +143,7 @@ void testGetServiceTokenSuccessfully(VaultEnvironment vaultEnvironment) throws E final var jwtToken = new JsonwebtokenResolver( JwksKeyLocator.builder().jwksUri(vaultEnvironment.jwksUri()).build()) - .resolve(serviceToken) + .resolveToken(serviceToken) .get(3, TimeUnit.SECONDS); assertNotNull(jwtToken, "jwtToken"); diff --git a/tokens/src/main/java/io/scalecube/security/tokens/jwt/JsonwebtokenResolver.java b/tokens/src/main/java/io/scalecube/security/tokens/jwt/JsonwebtokenResolver.java index a94670a..5c39667 100644 --- a/tokens/src/main/java/io/scalecube/security/tokens/jwt/JsonwebtokenResolver.java +++ b/tokens/src/main/java/io/scalecube/security/tokens/jwt/JsonwebtokenResolver.java @@ -1,13 +1,8 @@ package io.scalecube.security.tokens.jwt; -import com.fasterxml.jackson.databind.ObjectMapper; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.Locator; -import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.security.Key; -import java.util.Base64; -import java.util.Map; import java.util.Objects; import java.util.concurrent.CompletableFuture; import org.slf4j.Logger; @@ -24,7 +19,7 @@ public JsonwebtokenResolver(Locator keyLocator) { } @Override - public CompletableFuture resolve(String token) { + public CompletableFuture resolveToken(String token) { return CompletableFuture.supplyAsync( () -> { final var claimsJws = @@ -50,29 +45,6 @@ public CompletableFuture resolve(String token) { }); } - @Override - public JwtToken parse(String token) { - String[] parts = token.split("\\."); - if (parts.length != 3) { - throw new JwtTokenException("Invalid JWT format"); - } - - try { - final var urlDecoder = Base64.getUrlDecoder(); - final var headerJson = new String(urlDecoder.decode(parts[0]), StandardCharsets.UTF_8); - final var payloadJson = new String(urlDecoder.decode(parts[1]), StandardCharsets.UTF_8); - - final var mapper = new ObjectMapper(); - final var header = mapper.readValue(headerJson, Map.class); - final var claims = mapper.readValue(payloadJson, Map.class); - - //noinspection unchecked - return new JwtToken(header, claims); - } catch (IOException e) { - throw new JwtTokenException("Failed to decode JWT", e); - } - } - private static String mask(String data) { if (data == null || data.length() < 5) { return "*****"; diff --git a/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtToken.java b/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtToken.java index 163095b..828164e 100644 --- a/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtToken.java +++ b/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtToken.java @@ -1,5 +1,38 @@ package io.scalecube.security.tokens.jwt; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Base64; import java.util.Map; -public record JwtToken(Map header, Map payload) {} +public record JwtToken(Map header, Map payload) { + + /** + * Parses given JWT without verifying its signature. + * + * @param token jwt token + * @return parsed token + */ + public static JwtToken parseToken(String token) { + String[] parts = token.split("\\."); + if (parts.length != 3) { + throw new JwtTokenException("Invalid JWT format"); + } + + try { + final var urlDecoder = Base64.getUrlDecoder(); + final var headerJson = new String(urlDecoder.decode(parts[0]), StandardCharsets.UTF_8); + final var payloadJson = new String(urlDecoder.decode(parts[1]), StandardCharsets.UTF_8); + + final var mapper = new ObjectMapper(); + final var header = mapper.readValue(headerJson, Map.class); + final var claims = mapper.readValue(payloadJson, Map.class); + + //noinspection unchecked + return new JwtToken(header, claims); + } catch (IOException e) { + throw new JwtTokenException("Failed to decode JWT", e); + } + } +} diff --git a/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtTokenResolver.java b/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtTokenResolver.java index d326043..a85a276 100644 --- a/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtTokenResolver.java +++ b/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtTokenResolver.java @@ -10,13 +10,5 @@ public interface JwtTokenResolver { * @param token jwt token * @return async result with {@link JwtToken}, or error */ - CompletableFuture resolve(String token); - - /** - * Parses given JWT without verifying its signature. - * - * @param token jwt token - * @return parsed token - */ - JwtToken parse(String token); + CompletableFuture resolveToken(String token); }