javajwtjjwt

Java jjwt creating invalid JSON for JWT


I must be missing something. I am using the JJWT library to create JWTs. The JWTs are created inconsistently from the library depending on the data set in the claims. My code:

Date now = new Date();
Date expiration = new Date(now.getTime() + TimeUnit.MINUTES.toMillis(30));

Claims claims = Jwts.claims();

JSONObject jsonObject = new JSONObject();
jsonObject.put("serviceName1", "serviceStatus1");
jsonObject.put("serviceName2", "serviceStatus2");
claims.put("services",jsonObject);

claims.setSubject("225544");
claims.setExpiration(expiration);
claims.setId(UUID.randomUUID().toString());
claims.setIssuedAt(now);

return Jwts.builder()
    .setClaims(claims)
    .signWith(SignatureAlgorithm.HS256, Base64.encodeBase64(secret.getBytes()))
    .compact();

This code creates a JWT and signs it correctly. However, when the payload is decoded, the payload value is not always valid JSON. Most often it is missing the closing } causing any parsing of it to fail. If the Subject is 8 characters, it works fine. If it is 7 or 6 characters long, it is invalid JSON. Or if I add other tags to the claim, sometimes it works and sometimes it doesn't. Am I doing something wrong?

I have also tried using Auth0 java-JWT library and get similar results, Payload not always valid JSON.


Solution

  • Ultimately, I could not get the JJWT library working how I wanted. As such, I implemented a simple hashing algorithm and jwt creator manually. Here is what that looks like:

        Date now = new Date();
        //Valid only for 30 minutes
        Date expiration = new Date(now.getTime() + TimeUnit.MINUTES.toMillis(30));
    
        JSONObject header = new JSONObject();
        JSONObject payload = new JSONObject();
    
        header.put("alg", "HS256");
    
        payload.put("sub", "ourSubject");
        payload.put("exp", expiration.getTime() / 1000);
        payload.put("jti", UUID.randomUUID().toString());
        payload.put("iat", now.getTime() / 1000);
        payload.put("services", "JSON object of our custom data needed in authorization (not authentication");
        String signature = "";
    
        StringBuilder token = new StringBuilder();
        token.append(new String(Base64.encodeBase64(header.toString().getBytes())));
        token.append(".");
        token.append(new String(Base64.encodeBase64(payload.toString().getBytes())));
        try {
            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(Base64.encodeBase64((secret + otherPartOfSecret).getBytes()), "HmacSHA256");
            sha256_HMAC.init(secret_key);
    
            signature = new String(Base64.encodeBase64(sha256_HMAC.doFinal(token.toString().getBytes())));
        } catch (Exception e) {
            System.out.println("Error");
        }
    
        token.append(".");
        token.append(signature);
    
        return token.toString();