Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Auth0 java-jwt library fails to verify a valid token

I'm using the Auth0 java-jwt library to generate JWT tokens, however, once generated I'm not able to verify the tokens.

This is the code I use to generate the token:

final JWTSigner signer = new JWTSigner(secret);
final HashMap<String, Object> claims = new HashMap<String, Object>();
claims.put("user", user);
claims.put("email", user.getEmail());
final String jwt = signer.sign(claims);
return jwt;

This is my secret and the token (it verifies correctly in https://jwt.io/):

secret:
sfnd984f94j3fjn

token: eyJ0eXBlIjoiSldUIiwiYWxnIjoiSFMyNTYifQ.eyJ1c2VyIjp7ImlkIjoyLCJlbWFpbCI6InNhbnRob3NoQHh5ei5jb20iLCJwYXNzd29yZCI6IiQyYSQxMCRHSlNNRGtRRUEvRVNsRENJcVlud0R1Ly45YWRqRWRQalVvSWVKUmlsSmpSeHh6N2s2Q01xQyIsImZpcnN0X25hbWUiOiJzYW50aG9zaCIsImxhc3RfbmFtZSI6Imt1bWFyIiwic3RhdHVzIjoxLCJ0aXRsZSI6IkFzc29jIiwicm9sZXMiOlt7ImlkIjoxLCJyb2xlIjoiVVNFUiJ9XX0sImVtYWlsIjoic2FudGhvc2hAeHl6LmNvbSJ9.0SHNCgUWOijpYv7xcNoPiCwg_OFZQnsdi5l7YhCsSjU

When I use the same JWT token to verify it using the Auth0 method it fails (always ends up with a signature exception):

try {           
    final JWTVerifier verifier = new JWTVerifier(secret);
    final Map<String, Object> claims= verifier.verify(jwt);
    final String email = (String)claims.get("email");
    user =  userService.loadUserByEmail(email);
} catch (UsernameNotFoundException e) {
    // Invalid Token
} catch (SignatureException e) {
    System.out.println(e.toString());
} catch (IOException e) { 
} catch (Exception e) { 
}

I debugged the library and I think this is where the issue is (in JWTVerifier class):

void verifySignature(String[] pieces, String algorithm) 
    throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {

    Mac hmac = Mac.getInstance(algorithm);
    hmac.init(new SecretKeySpec(decoder.decodeBase64(secret), algorithm));
    byte[] sig = hmac.doFinal(
        new StringBuilder(pieces[0]).append(".").append(pieces[1]).toString().getBytes());

    if (!Arrays.equals(sig, decoder.decodeBase64(pieces[2]))) {
        throw new SignatureException("signature verification failed");
    }
}

This looks wrong to me because the pieces[1] and pieces[0] are decoded with the hmac.doFinal where as the pieces[2] is just plain base64 decoded.

Is my assumption right. Is this a bug in the library or am I getting something wrong?

like image 709
swordfish Avatar asked Jul 03 '26 15:07

swordfish


1 Answers

The version of JWTVerifier being used assumes that the secret you pass is Base64url encoded so it automatically decodes it before using it as the key to validate the signature.

Given sfnd984f94j3fjn is the actual secret and your version of JWTVerifier automatically Base64url decodes whatever you pass it, you need to encode sfnd984f94j3fjn in Base64url and pass the encoded version to JWTVerifier.

Something similar to this:

import org.apache.commons.codec.binary.Base64;

// ...

Base64 encoder = new Base64(true);

encoder.encodeBase64("sfnd984f94j3fjn".getBytes());

You can see the automatic decoding of the secret happening on the following line of the version of JWTVerifier class you're using:

hmac.init(new SecretKeySpec(decoder.decodeBase64(secret), algorithm));

An update on this, the latest version of the library does not seem to assume a Base64url encoding.

like image 106
João Angelo Avatar answered Jul 05 '26 04:07

João Angelo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!