auth0 / java-jwt

Java implementation of JSON Web Token (JWT)
MIT License
5.84k stars 921 forks source link

Support for the absence of payload #647

Closed cesarcneto closed 1 year ago

cesarcneto commented 1 year ago

Describe the problem you'd like to have solved

I'm trying to integrate my service with a 3rd party API. They provided me with this "how to" documentation.

I currently cannot generate a JWT signature using com.auth0:java-jwt:4.2.1 that yields an empty payload section. The JWTs generated by the library always yields the payload part as the encoded value e30. Below you can find the example of JWT I'm currently generating.

E.g.: eyJwYXhvcy5jb20vcmVxdWVzdC1wYXRoIjoiL3YyL3RyYW5zZmVyL3RyYW5zZmVycz9saW1pdD0xMCIsInBheG9zLmNvbS9yZXF1ZXN0LW1ldGhvZCI6IkdFVCIsImtpZCI6IjM1Yjc5YTE1LWQ3ZDEtNDdhYi1hYTRjLWZkMjRlYzkzOTlkYSIsInBheG9zLmNvbS90aW1lc3RhbXAiOiIxNjcyMDU4NzU1OTMzIiwidHlwIjoiSldUIiwiYWxnIjoiRVMyNTYifQ.e30.bSnVsYfuobKWRF4DCYCByRdPM5j58FZODeUny9QCEXaNeaRHusMOSLBswpTxn7aJZbuuMyOuq6vmWKK8AllSGQ

My need is that, for GET requests, I should be able to generate a JWT with the payload part being absent.

Describe the ideal solution

The python library pyjwt[crypto] supports this use case.

E.g.

>>> import jwt
>>> payload = b''
>>> with open('./my-private-ec.pem', 'rb') as f: key = f.read()
... 
>>> alg = "ES256"
>>> headers = {"kid": "5498f424-78aa-414b-a515-13929e6951db", "alg": alg, 
               "paxos.com/timestamp": "1645503272",
               "paxos.com/request-method" : "GET", 
               "paxos.com/request-path": "/v2/transfer/deposit-addresses"}
>>> signature = jwt.api_jws.encode(payload=payload, key=key, headers=headers, 
                                   algorithm=alg)
>>> print(signature)
eyJhbGciOiJFUzI1NiIsImtpZCI6IjU0OThmNDI0LTc4YWEtNDE0Yi1hNTE1LTEzOTI5ZTY5NTFkYiIsInBheG9zLmNvbS9yZXF1ZXN0LW1ldGhvZCI6IkdFVCIsInBheG9zLmNvbS9yZXF1ZXN0LXBhdGgiOiIvdjIvdHJhbnNmZXIvZGVwb3NpdC1hZGRyZXNzZXMiLCJwYXhvcy5jb20vdGltZXN0YW1wIjoiMTY0NTUwMzI3MiIsInR5cCI6IkpXVCJ9..d3bzuIZmoqvbamKL-c_7WlKCWqrjUBCEyDFuu-tWR350r1SsehbJ1b0adQmWD7Ekl46NqQOTO17Hcfb9pTBWmA

Note the payload section. It is absent. And that's exactly what com.auth0:java-jwt:4.2.1 is not supporting.

Alternatives and current work-arounds

At the moment I cannot use com.auth0:java-jwt as I couldn't find a workaround with it. My go-to library ended up being https://github.com/jwtk/jjwt

cesarcneto commented 1 year ago

From what I checked, it seems I'm asking for a behavior that does not conform with the JWT payload spec. Therefore, I'm closing this issue.

cesarcneto commented 1 year ago

Well. After a deeper look, I've found this:

Note that the payload can be any content and need not be a representation of a JSON object.

Source: https://www.rfc-editor.org/rfc/rfc7515#section-3.3

Maybe something you'd like to consider?

jimmyjames commented 1 year ago

Hey @cesarcneto, thanks for raising and apologies for not replying sooner, just been tied up with other initiatives and holidays, etc...

You are correct that in general the request conflicts with the JWT spec, but the JWS spec you posted makes it more interesting 🤔. I'll need to investigate more and discuss with colleagues and then will follow-up

jimmyjames commented 1 year ago

Using a JWT with an empty payload in jwt.io displays the following:

Looks like your JWT payload is not a valid JSON object. JWT payloads must be top level JSON objects as per https://tools.ietf.org/html/rfc7519#section-7.2

From that section of RFC7519:

Verify that the resulting octet sequence is a UTF-8-encoded representation of a completely valid JSON object conforming to RFC 7159 [RFC7159]; let the JWT Claims Set be this JSON object.

I agree that RFC7515 seems to conflict on this point, but as RFC7519 specifies a valid JSON payload we aren't going to support this right now, but will consider supporting in a future version if additional requests or learnings show that we should.