Jaroslav Záruba
Jaroslav Záruba

Reputation: 4876

DefaultJwtParser: how to merely decode the JWT? (no secret key, no validation)

I don't want to verify the JWT using the secret key (which I don't have), I only want to decode the JWT and read the payload. Can this be achieved using jsonwebtoken.io:jjwt? It seems like there is a method missing in the API.

Of course, I could split-&-Base64-decode the token myself but it feels like the most basic functionality one would expect from a JWT-library; hence I suspect I am missing something.

Upvotes: 23

Views: 19118

Answers (4)

Jon X
Jon X

Reputation: 9133

Try to use the JWTParser.parse(token) of the com.nimbusds:nimbus-jose-jwt:{version}:

        <dependency>
            <groupId>com.nimbusds</groupId>
            <artifactId>nimbus-jose-jwt</artifactId>
            <version>9.37.3</version>
        </dependency>
import java.text.ParseException;
import java.util.Map;

import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTParser;

public class Main {
    public static void main(String[] args) throws ParseException {
        String token = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJZRU9iU1ZKdWZsem9WYW1KX05EbnZUbFA1SVNRVXNaRzRBVUZlWDFGZVFrIn0.eyJleHAiOjE3MDQ0MzAyODksImlhdCI6MTcwNDQyOTk4OSwianRpIjoiMjhlNzE4N2YtM2EwNS00YTQxLWJiODUtYmJiZDg4MDM3OTRkIiwiaXNzIjoiaHR0cDovL25vZGUtMDo4MDgwL3JlYWxtcy9zcG1pYS1yZWFsbSIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiI1NTk0OGNmMS04ZTNiLTQ4ZjUtYThkOC1lMGJmMDI2NDRjNjkiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJvc3RvY2siLCJzZXNzaW9uX3N0YXRlIjoiNjgxODIwOGYtZTM5Yy00NjQ3LWEzMjEtMTQ4YWU5MmJhMmE5IiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyIqIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsImRlZmF1bHQtcm9sZXMtc3BtaWEtcmVhbG0iLCJ1bWFfYXV0aG9yaXphdGlvbiIsIm9zdG9jay1hZG1pbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7Im9zdG9jayI6eyJyb2xlcyI6WyJBRE1JTiJdfSwiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwic2lkIjoiNjgxODIwOGYtZTM5Yy00NjQ3LWEzMjEtMTQ4YWU5MmJhMmE5IiwiZW1haWxfdmVyaWZpZWQiOnRydWUsInByZWZlcnJlZF91c2VybmFtZSI6ImlsbGFyeS5odWF5bHVwbyJ9.NF0MzYSVkfDTo4YT8wmyibeY-D14C9J1kpCa5EUTRXQbdZX3Wbo053UsqlMMV6NVdG7jjQb1sG3So-nL-H6MLZyg0nmnfsmcnR5j315I6NCqGuJnMXxmbVxqUQViLW1lenJDGkDk2IOr2uJDcdTUR6pSemhnaXKOY47vEJ5dTTlvS73rJ1FQHKEv3kj50SjhgBSzRNuR7Ejghfnnp5kEXSekv40hLFXhE4Som_ZJ8IsYzTOvBMPnbYa5STNgprhcOlvmeiswXDrtyH2udd4qxxURivX7VAVT-Qt8_ozvGyQr7V4u5f4NRq-5i-SVYJtIjqwQOxnUrUMjzF1IDtCqow";
        JWT jwt = JWTParser.parse(token);
        Map<String, Object> claims = jwt.getJWTClaimsSet().getClaims();

        for (String key : claims.keySet()) {
            System.out.printf("%s: %s\n", key, claims.get(key));
        }
    }
}

The nimbus-jose-jwt is also used by the org.springframework.boot:spring-boot-starter-oauth2-resource-server:

[INFO] +- org.springframework.boot:spring-boot-starter-oauth2-resource-server:jar:3.2.1:compile
[INFO] |  +- org.springframework.security:spring-security-config:jar:6.2.1:compile
[INFO] |  +- org.springframework.security:spring-security-core:jar:6.2.1:compile
[INFO] |  |  \- org.springframework.security:spring-security-crypto:jar:6.2.1:compile
[INFO] |  +- org.springframework.security:spring-security-oauth2-resource-server:jar:6.2.1:compile
[INFO] |  |  +- org.springframework.security:spring-security-oauth2-core:jar:6.2.1:compile
[INFO] |  |  \- org.springframework.security:spring-security-web:jar:6.2.1:compile
[INFO] |  \- org.springframework.security:spring-security-oauth2-jose:jar:6.2.1:compile
[INFO] |     \- com.nimbusds:nimbus-jose-jwt:jar:9.24.4:compile
[INFO] |        \- com.github.stephenc.jcip:jcip-annotations:jar:1.0-1:compile

BTW, I also tried to use the io.jsonwebtoken, but it seems that it required to verify the signature of the token. Such as The JWS header references signature algorithm 'RS256' but the compact JWE string is missing the required signature.

Upvotes: 3

overflown stack
overflown stack

Reputation: 31

If you can use another library, it can be done as accepted answer here: How to decode JWT token to get details of Header and Payload using nimbus-jose-jwt?

Repeating the answer here:
dependency: com.nimbusds:nimbus-jose-jwt:<version>
usage:

/**
 * accessToken: the JWT string text.
**/
private String parseJWT(String accessToken) {
    try {
        var decodedJWT = SignedJWT  // or PlainJWT or EncryptedJWT
                           .parse(accessToken);
        var header = decodedJWT.getHeader().toString();
        var payload = decodedJWT.getPayload().toString();
    } catch (ParseException e) {
        throw new Exception("Invalid token!");
    }
}

Upvotes: 3

Blink
Blink

Reputation: 1546

Maybe use the Auth0 library instead?

DecodedJWT jwt = JWT.decode(token);
jwt.getToken();

Dependencies:

<dependency>
  <groupId>com.auth0</groupId>
  <artifactId>java-jwt</artifactId>
  <version>3.8.3</version>
</dependency>
<dependency>
  <groupId>com.auth0</groupId>
  <artifactId>jwks-rsa</artifactId>
  <version>0.9.0</version>
</dependency>

Example taken from https://medium.com/trabe/validate-jwt-tokens-using-jwks-in-java-214f7014b5cf

Upvotes: 6

bidisha mukherjee
bidisha mukherjee

Reputation: 745

Try the following code:

int i = jws.lastIndexOf('.')
String withoutSignature = jws.substring(0, i+1);
Jwt<Header,Claims> untrusted = Jwts.parser().parseClaimsJwt(withoutSignature);

You can 'chop off' the last 'part' after the last period character ('.'), which is the JWS signature.And then read that JWT as a 'normal' JWT (non-JWS).

What you are asking for is to ignore the signature on a valid JWS and read the JWT header and body anyway. This violates the JWS specification, and because of that JJWT does not support it.

This is taken from this github issue, which I guess is same as you are facing.

Upvotes: 33

Related Questions