2

Using the online JWT debugger to encode and decode a JWT token I created this simple token

https://jwt.io/#debugger-io?token=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImF1ZCI6IlNvbHIifQ.5T7L_L1MPfQ_5FjKGa1fTPqrzwK4bNSM812nW6oyjb8

The secret to encode the token is
qwertypassword

The header is { "alg": "HS256"}

The payload is { "sub": "admin", "aud": "Solr"}

When you encoded with the secret not base64 encoded, it generates the JWT eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImF1ZCI6IlNvbHIifQ.5T7L_L1MPfQ_5FjKGa1fTPqrzwK4bNSM812nW6oyjb8

When the secret is base64 encoded it generates the JWT eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImF1ZCI6IlNvbHIifQ.SWCJDd6B_m7xr_puQH-wgbxvXyJYXH9lTpldOU0eQKc

Here is the Java code to generate the JWT for when the secret is not base64 encoded.

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
public class JWTEncodeTest {
    public static void main(String[] args) {
        try {
            String secretkey="qwertypassword";

            //The JWT signature algorithm we will be using to sign the token
            String jwtToken = Jwts.builder()
                .setSubject("admin")
                .setAudience("Solr")
                .signWith(SignatureAlgorithm.HS256,secretkey.getBytes()).compact();

            System.out.println("jwtToken=");
            System.out.println(jwtToken);
        } catch (Exception e)
        {
            System.out.println(e.getMessage());
        }
    }
}

What am I missing in this Java code to generate the JWT with the secret base64 encoded to produce the JWT value of

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImF1ZCI6IlNvbHIifQ.SWCJDd6B_m7xr_puQH-wgbxvXyJYXH9lTpldOU0eQKc

jps
  • 20,041
  • 15
  • 75
  • 79
tigger
  • 95
  • 1
  • 2
  • 8
  • What is the problem you have? Can't you just base64 encode your `secretkey`? See https://stackoverflow.com/questions/13109588/encoding-as-base64-in-java for how you use base64. – Progman Sep 22 '19 at 08:06

2 Answers2

5

The meaning of secret base64 encoded on jwt.io is actually, that it treats the secret you provide as base64encoded and therefore first decodes it, before it is actually used. The point is not to create anything different, but just to decode the secret when it is encoded.

The secret you used is, in it's clear, not encoded form:

qwertypassword

When you base64 encode it, eg. with the help of https://www.base64encode.org/, you get this as base64 encoded value:

cXdlcnR5cGFzc3dvcmQ=

On jwt.io you can use both forms:

  • the first, not encoded one with the base64 encoded secret checkbox unchecked

    or

  • the second, base64 encoded one with the checkbox checked.

In both cases you would get the same result.

For your java code it would require an extra step to decode the encoded secret, before using it to sign:

import java.util.Base64;

String base64EncodedSecret = "cXdlcnR5cGFzc3dvcmQ=";
byte[] decodedSecret = Base64.getDecoder().decode(base64EncodedSecret);

and then, when you create the JWT, you use the decoded secret:

.signWith(SignatureAlgorithm.HS256, decodedSecret)

But that's only necessary, if you get the secret for some reason in encoded form.

jps
  • 20,041
  • 15
  • 75
  • 79
  • This doesn't work the JWT token at https://jwt.io/#debugger-io?token=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImF1ZCI6IlNvbHIiLCJleHAiOjE1NjkwMzY5NTl9.CTL0HdcqBtq5fS2Uf2M3UqIxmInAE24dzQ2ybIsOoO4 when the secret base64 endcoded is checked produces the JWT token eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImF1ZCI6IlNvbHIiLCJleHAiOjE1NjkwMzY5NTl9.CTL0HdcqBtq5fS2Uf2M3UqIxmInAE24dzQ2ybIsOoO4 The Java code produces eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImF1ZCI6IlNvbHIifQ.5T7L_L1MPfQ_5FjKGa1fTPqrzwK4bNSM812nW6oyjb8 – tigger Sep 22 '19 at 22:00
  • If you really want to treat `qwertypassword` as base64 encoded value, then just replace the contents of the `base64encodedSecret`variable with `quertypassword`. But in my answer I tried to explain how to use base64 encoding. My focus was not to reproduce the exact result of treating your secret as base64 encoded, because it is not really a base 64 encoded value. It doesn't make sense to just take a random string and say it is base64 encoded. Therefore I showed you how your random secret would look like in base64 encoded form. Please read my answer again carefully. – jps Sep 23 '19 at 07:39
  • Thanks this did work String secretkey="qwertypassword"; byte[] decodedSecret = Base64.getDecoder().decode(secretkey); ... .signWith(SignatureAlgorithm.HS256,decodedSecret).compact(); Produces the JWT key I was expecting. – tigger Sep 24 '19 at 14:53
  • Better to call `.signWith(Keys.hmacShaKeyFor(decodedSecret))` – Les Hazlewood Sep 25 '19 at 20:22
  • I miss understood the option, secret base64 encoded. When it's checked, the value you entered in that box will be base64 decoded. I thought the other way around. So glad to find the discussion here, and up voted already. – Dino Tw Aug 15 '21 at 04:49
0

Here is the code for the solution that worked for me, based on JPS feedback

import io.jsonwebtoken.SignatureAlgorithm;    
import io.jsonwebtoken.Jwts;
import java.util.Base64;


public class JWT {

    public static void main(String[] args) {
        try {
            String secretkey="qwertypassword";
            byte[] decodedSecret = Base64.getDecoder().decode(secretkey);

            //The JWT signature algorithm we will be using to sign the token
            String jwtToken = Jwts.builder()
                .setSubject("admin")
                .setAudience("Solr")
                .signWith(SignatureAlgorithm.HS256,decodedSecret).compact();

            System.out.println("jwtToken=");
            System.out.println(jwtToken);
        } catch (Exception e)
        {
            System.out.println(e.getMessage());
        }
    }
}

The value of the JWT key is the expected

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImF1ZCI6IlNvbHIifQ.SWCJDd6B_m7xr_puQH-wgbxvXyJYXH9lTpldOU0eQKc

That the site https://jwt.io/#debugger-io?token=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImF1ZCI6IlNvbHIifQ.5T7L_L1MPfQ_5FjKGa1fTPqrzwK4bNSM812nW6oyjb8

produces.

tigger
  • 95
  • 1
  • 2
  • 8