Repository navigation
Conversation
Use the existing claim-specific errors before integer conversion. Cover boolean values and disabled claim verification.
19dd77c to
17060ce
Compare
TheSingulant
left a comment
There was a problem hiding this comment.
Agreed that a JSON boolean isn't a NumericDate, and checking before the int() conversion is the right spot. I ran the new tests against master's api_jwt.py: all six boolean cases fail there and pass here, including exp, where the message match is what separates the new error from ExpiredSignatureError. One question about the encode side.
| def test_decode_rejects_boolean_numericdate( | ||
| self, jwt: PyJWT, claim: str, error: type[Exception], value: bool | ||
| ) -> None: | ||
| token = jwt.encode({claim: value}, "a" * 32, algorithm="HS256") |
There was a problem hiding this comment.
This line shows the other half of the issue: jwt.encode() still issues a token with a boolean exp/nbf/iat that decode() now refuses (I checked: encode({"exp": True}, ...) succeeds, and decoding it raises the new DecodeError). encode() already rejects a non-string iss with TypeError (the #1039 check), so rejecting booleans in the time claims there seems consistent. Is that in scope here, or better as a follow-up? If it lands, these tests would need to build the token without going through jwt.encode, e.g. by signing a hand-serialized payload with jwt.api_jws.encode.
There was a problem hiding this comment.
thanks, good catch — added to this PR. encode() now raises TypeError for bool exp/nbf/iat (same as iss in #1039), and the decode tests sign the payload with jwt.api_jws.encode as you suggested
There was a problem hiding this comment.
Thanks, this looks good. Rejecting bools at encode time keeps encode and decode consistent, and building the decode tokens through api_jws.encode means those tests now cover the decode-side check directly. The is True assertion in the verification-disabled case is a nice touch. LGTM from my side.
Raise TypeError, as for a non-string iss (jpadilla#1039). Build the decode test tokens with jwt.api_jws.encode.
decode()accepts JSON booleans inexp,nbfandiat. Python'sboolis a subclass ofint, soTruebecomes1andFalsebecomes0. On currentmaster:A boolean
nbforiatis accepted. A booleanexpraisesExpiredSignatureError. RFC 7519 §2 defines NumericDate as a JSON number, and a boolean is not a number.In
decode(), this PR checks forboolbefore the integer conversion. It raises the same errors as #1186 does for other non-numeric values. Numeric strings are still accepted (#847). When verification of the claim is disabled, decoding works as before. The change merges cleanly with #1191.encode()now raisesTypeErrorfor a booleanexp,nbforiat, as it does for a non-stringiss(#1039). On this branch, theencode()line of the example above raisesTypeError.Tests: 15 new cases: 6 for
encode(), 6 fordecode(), 3 with verification disabled. The boolean-claimdecode()tests serialize the payload withjson.dumpsand sign it withjwt.api_jws.encode. The full suite passes on Python 3.9 and 3.14.How it was found: a check of pyjwt against JOSE RFC requirements in the acceptance format. The fix rests on these rows:
NumericDate JOSE-7519-2-1,
expJOSE-7519-4.1.4-2,nbfJOSE-7519-4.1.5-2, andiatJOSE-7519-4.1.6-1.