Skip to content

Commit

Permalink
Merge pull request #66 from snegrus-adb/snegrus/check-jwt-structure
Browse files Browse the repository at this point in the history
Check header look like JWT before processing
  • Loading branch information
j-baker authored Jul 3, 2018
2 parents 948d21a + 5397c88 commit 5f4f134
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

package com.palantir.tokens.auth.http;

import com.palantir.tokens.auth.AuthHeader;
import com.palantir.tokens.auth.UnverifiedJsonWebToken;
import java.util.Optional;
import javax.annotation.Priority;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
Expand Down Expand Up @@ -51,16 +51,12 @@ public final void filter(ContainerRequestContext requestContext) {
return;
}

try {
UnverifiedJsonWebToken jwt = UnverifiedJsonWebToken.of(
AuthHeader.valueOf(rawAuthHeader).getBearerToken());

Optional<UnverifiedJsonWebToken> parsedJwt = UnverifiedJsonWebToken.tryParse(rawAuthHeader);
parsedJwt.ifPresent(jwt -> {
setUnverifiedContext(requestContext, USER_ID_KEY, jwt.getUnverifiedUserId());
jwt.getUnverifiedSessionId().ifPresent(s -> setUnverifiedContext(requestContext, SESSION_ID_KEY, s));
jwt.getUnverifiedTokenId().ifPresent(s -> setUnverifiedContext(requestContext, TOKEN_ID_KEY, s));
} catch (Throwable t) {
log.debug("Unable to process auth header.", t);
}
});
}

private void clearMdc() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import java.util.Optional;
import java.util.UUID;
import org.immutables.value.Value;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Represents the parsed form of a JWT but does not verify the token signature.
Expand All @@ -46,6 +48,8 @@ public abstract class UnverifiedJsonWebToken {
.registerModule(new Jdk8Module())
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

private static final Logger log = LoggerFactory.getLogger(UnverifiedJsonWebToken.class);

/**
* Returns the unverified user id, i.e., the "sub" (subject) field of the JWT.
*/
Expand All @@ -66,6 +70,21 @@ public abstract class UnverifiedJsonWebToken {
@Value.Parameter
public abstract Optional<String> getUnverifiedTokenId();

/**
* Does a lower cost check on the structure of string provided
* before attempting to create an {@link UnverifiedJsonWebToken}.
*/
public static Optional<UnverifiedJsonWebToken> tryParse(String rawAuthHeader) {
if (rawAuthHeader.chars().filter(x -> x == '.').count() == 2) {
try {
return Optional.of(of(AuthHeader.valueOf(rawAuthHeader).getBearerToken()));
} catch (Throwable t) {
log.debug("Unable to process auth header.", t);
}
}
return Optional.empty();
}

/**
* Attempts to create an {@link UnverifiedJsonWebToken} from provided {@link BearerToken}.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,31 @@ public void testAsJwt_validJwtFromSessionToken() {
@Test
public void testAsJwt_validJwtFromApiToken() {
UnverifiedJsonWebToken token = UnverifiedJsonWebToken.of(API_TOKEN);
assertEquals(USERID, token.getUnverifiedUserId());
assertEquals(Optional.empty(), token.getUnverifiedSessionId());
assertEquals(Optional.of(TOKEN_ID), token.getUnverifiedTokenId());
assertValidApiToken(token);
}

@Test
public void testAsJwt_validJwtFromProxyToken() {
UnverifiedJsonWebToken token = UnverifiedJsonWebToken.of(PROXY_TOKEN);
assertEquals(USERID, token.getUnverifiedUserId());
assertEquals(Optional.empty(), token.getUnverifiedSessionId());
assertEquals(Optional.of(TOKEN_ID), token.getUnverifiedTokenId());
assertValidApiToken(token);
}

@Test
public void testAsJwt_validJwtFromParsedToken() {
Optional<UnverifiedJsonWebToken> token = UnverifiedJsonWebToken.tryParse(PROXY_TOKEN.getToken());
assertValidApiToken(token.get());
}

@Test
public void invalidJwt_parseReturnsEmpty() {
Optional<UnverifiedJsonWebToken> parsedJwt = UnverifiedJsonWebToken.tryParse(INVALID_BEARER_TOKEN.getToken());
assertEquals(parsedJwt, Optional.empty());
}

@Test
public void invalidJwt_parseReturnsEmpty_validStructure() {
Optional<UnverifiedJsonWebToken> parsedJwt = UnverifiedJsonWebToken.tryParse(INVALID_PAYLOAD_TOKEN.getToken());
assertEquals(parsedJwt, Optional.empty());
}

@Test
Expand All @@ -90,4 +104,10 @@ public void invalidJwt_invalidPayloadToken() {
assertEquals("Invalid JWT: cannot parse payload", e.getMessage());
}
}

private void assertValidApiToken(UnverifiedJsonWebToken token) {
assertEquals(USERID, token.getUnverifiedUserId());
assertEquals(Optional.empty(), token.getUnverifiedSessionId());
assertEquals(Optional.of(TOKEN_ID), token.getUnverifiedTokenId());
}
}

0 comments on commit 5f4f134

Please sign in to comment.