Skip to content

Commit ff70e76

Browse files
authored
Added new function - JwtTokenResolver.parse() (#113)
2 parents 71c506d + 5b76f4e commit ff70e76

File tree

3 files changed

+59
-4
lines changed

3 files changed

+59
-4
lines changed

tests/src/test/java/io/scalecube/security/tokens/jwt/JsonwebtokenResolverTests.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,25 @@ void testResolveTokenSuccessfully(VaultEnvironment vaultEnvironment) throws Exce
4343
assertTrue(jwtToken.payload().size() > 0, "jwtToken.payload: " + jwtToken.payload());
4444
}
4545

46+
@Test
47+
void testParseTokenSuccessfully(VaultEnvironment vaultEnvironment) {
48+
final var token = vaultEnvironment.newServiceToken();
49+
50+
final var jwtToken =
51+
new JsonwebtokenResolver(
52+
JwksKeyLocator.builder()
53+
.jwksUri(vaultEnvironment.jwksUri())
54+
.connectTimeout(Duration.ofSeconds(3))
55+
.requestTimeout(Duration.ofSeconds(3))
56+
.keyTtl(1000)
57+
.build())
58+
.parse(token);
59+
60+
assertNotNull(jwtToken, "jwtToken");
61+
assertTrue(jwtToken.header().size() > 0, "jwtToken.header: " + jwtToken.header());
62+
assertTrue(jwtToken.payload().size() > 0, "jwtToken.payload: " + jwtToken.payload());
63+
}
64+
4665
@Test
4766
void testJwksKeyLocatorThrowsError(VaultEnvironment vaultEnvironment) {
4867
final var token = vaultEnvironment.newServiceToken();

tokens/src/main/java/io/scalecube/security/tokens/jwt/JsonwebtokenResolver.java

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
package io.scalecube.security.tokens.jwt;
22

3+
import com.fasterxml.jackson.databind.ObjectMapper;
34
import io.jsonwebtoken.Jwts;
45
import io.jsonwebtoken.Locator;
6+
import java.io.IOException;
7+
import java.nio.charset.StandardCharsets;
58
import java.security.Key;
9+
import java.util.Base64;
10+
import java.util.Map;
611
import java.util.Objects;
712
import java.util.concurrent.CompletableFuture;
813
import org.slf4j.Logger;
@@ -30,21 +35,44 @@ public CompletableFuture<JwtToken> resolve(String token) {
3035
(jwtToken, ex) -> {
3136
if (jwtToken != null) {
3237
if (LOGGER.isDebugEnabled()) {
33-
LOGGER.debug("Resolved token: {}", mask(token));
38+
LOGGER.debug("Resolved JWT: {}", mask(token));
3439
}
3540
return jwtToken;
3641
}
3742
if (ex != null) {
3843
if (ex instanceof JwtTokenException) {
3944
throw (JwtTokenException) ex;
4045
} else {
41-
throw new JwtTokenException("Failed to resolve token: " + mask(token), ex);
46+
throw new JwtTokenException("Failed to resolve JWT: " + mask(token), ex);
4247
}
4348
}
4449
return null;
4550
});
4651
}
4752

53+
@Override
54+
public JwtToken parse(String token) {
55+
String[] parts = token.split("\\.");
56+
if (parts.length != 3) {
57+
throw new JwtTokenException("Invalid JWT format");
58+
}
59+
60+
try {
61+
final var urlDecoder = Base64.getUrlDecoder();
62+
final var headerJson = new String(urlDecoder.decode(parts[0]), StandardCharsets.UTF_8);
63+
final var payloadJson = new String(urlDecoder.decode(parts[1]), StandardCharsets.UTF_8);
64+
65+
final var mapper = new ObjectMapper();
66+
final var header = mapper.readValue(headerJson, Map.class);
67+
final var claims = mapper.readValue(payloadJson, Map.class);
68+
69+
//noinspection unchecked
70+
return new JwtToken(header, claims);
71+
} catch (IOException e) {
72+
throw new JwtTokenException("Failed to decode JWT", e);
73+
}
74+
}
75+
4876
private static String mask(String data) {
4977
if (data == null || data.length() < 5) {
5078
return "*****";

tokens/src/main/java/io/scalecube/security/tokens/jwt/JwtTokenResolver.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,18 @@
55
public interface JwtTokenResolver {
66

77
/**
8-
* Verifies and returns token claims.
8+
* Verifies given JWT and parses its header and claims.
99
*
1010
* @param token jwt token
11-
* @return mono result with parsed claims (or error)
11+
* @return async result with {@link JwtToken}, or error
1212
*/
1313
CompletableFuture<JwtToken> resolve(String token);
14+
15+
/**
16+
* Parses given JWT without verifying its signature.
17+
*
18+
* @param token jwt token
19+
* @return parsed token
20+
*/
21+
JwtToken parse(String token);
1422
}

0 commit comments

Comments
 (0)