How to decode JWT (Header and Body) in java using Apache Commons Codec?
Asked Answered
E

3

37

I am looking decode the following JWT using Apache Commons Codec. How we can do that ?

    eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0Iiwicm9sZXMiOiJST0xFX0FETUlOIiwiaXNzIjoibXlzZ
WxmIiwiZXhwIjoxNDcxMDg2MzgxfQ.1EI2haSz9aMsHjFUXNVz2Z4mtC0nMdZo6bo3-x-aRpw

This should retrieve Header, Body and Signature part. Whats the code ?

Elderly answered 12/8, 2016 at 11:29 Comment(0)
E
93

Here you go:

import org.apache.commons.codec.binary.Base64;
@Test
    public void testDecodeJWT(){
        String jwtToken = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0Iiwicm9sZXMiOiJST0xFX0FETUlOIiwiaXNzIjoibXlzZWxmIiwiZXhwIjoxNDcxMDg2MzgxfQ.1EI2haSz9aMsHjFUXNVz2Z4mtC0nMdZo6bo3-x-aRpw";
        System.out.println("------------ Decode JWT ------------");
        String[] split_string = jwtToken.split("\\.");
        String base64EncodedHeader = split_string[0];
        String base64EncodedBody = split_string[1];
        String base64EncodedSignature = split_string[2];

        System.out.println("~~~~~~~~~ JWT Header ~~~~~~~");
        Base64 base64Url = new Base64(true);
        String header = new String(base64Url.decode(base64EncodedHeader));
        System.out.println("JWT Header : " + header);


        System.out.println("~~~~~~~~~ JWT Body ~~~~~~~");
        String body = new String(base64Url.decode(base64EncodedBody));
        System.out.println("JWT Body : "+body);        
    }

The output below:

------------ Decode JWT ------------
~~~~~~~~~ JWT Header ~~~~~~~
JWT Header : {"alg":"HS256"}
~~~~~~~~~ JWT Body ~~~~~~~
JWT Body : {"sub":"test","roles":"ROLE_ADMIN","iss":"myself","exp":1471086381}
Elderly answered 12/8, 2016 at 11:29 Comment(0)
P
22

Here is a non-package-import way:

            java.util.Base64.Decoder decoder = java.util.Base64.getUrlDecoder();
            String[] parts = jwtToken.split("\\."); // split out the "parts" (header, payload and signature)

            String headerJson = new String(decoder.decode(parts[0]));
            String payloadJson = new String(decoder.decode(parts[1]));
            //String signatureJson = new String(decoder.decode(parts[2]));

REGARDLESS (of this alternative to org.apache.commons.codec.binary.Base64 SiKing'sanswer )... you may want to also push those json fragments to pojo's.

You can then take those json fragments and turn them into pojo.

The headers are "dynamic" (as in, you don't know all the header-names beforehand), so you probably want to convert to Key Value pairs (aka "Map" in java)

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.Map;

public class JwtTokenHeaders {

    private final Map<String, Object> jsonMap; // = new HashMap<String, Object>();

    public JwtTokenHeaders(String jsonString) {

        ObjectMapper mapper = new ObjectMapper();
        //String jsonString = "{\"name\":\"JavaInterviewPoint\", \"department\":\"blogging\"}";

        //Map<String, Object> jsonMap = new HashMap<String, Object>();
        try {
            // convert JSON string to Map
            this.jsonMap = mapper.readValue(jsonString,
                    new TypeReference<Map<String, String>>() {
                    });
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    @Override
    public String toString() {
        return org.apache.commons.lang3.builder.ToStringBuilder.reflectionToString(this);
    }
}

the payload (aka, the body) is more well-defined, so you can map to a pojo..... you can take the json and create a matching pojo here:

http://pojo.sodhanalibrary.com/

after you use an online tool (or hand craft the pojo youself)..to create something like "MyPojo(.java)"....

you'll end up with something like this:

//import com.fasterxml.jackson.databind.DeserializationFeature;
//import com.fasterxml.jackson.databind.ObjectMapper;
            ObjectMapper mapper = new ObjectMapper();
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            MyPojo tp = mapper.readValue(payloadJson, MyPojo.class);

if http://pojo.sodhanalibrary.com/ ceases to exist in the future, just internet search "online json to pojo" and you'll probably find something.

Pericardium answered 11/4, 2019 at 15:44 Comment(0)
E
2

Excellent! I simplified this work wrapping it up in a method with java.util.Base64 native package decoder to get user_id claim from payoad token:

Base64.Decoder base64Url = Base64.getUrlDecoder();

public static String getUserIdFromToken(String token) throws IOException {
    //"------------ Decode JWT ------------");
    String[] split_string = token.split("\\.");
    String base64EncodedBody = split_string[1];
    Base64.Decoder base64Url = Base64.getUrlDecoder();
    Map<String, Object> mapping = new ObjectMapper().readValue(base64Url.decode(base64EncodedBody), HashMap.class);

    return mapping.get("user_id").toString();
}
Etiolate answered 30/11, 2023 at 20:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.