Summary
Ruby issues and validates the JWT nbf (not before) claim. Python, PHP and Node ignore it. The same token, with the same secret, gets two different answers depending on which framework verifies it.
Where
Ruby, which is the correct one:
# lib/tina4/auth.rb:163 (issues it)
"nbf" => now
# lib/tina4/auth.rb:149 (validates it)
return nil if payload["nbf"] && now < payload["nbf"]
Python (tina4_python/auth/__init__.py, valid_token), PHP (Tina4/Auth.php) and Node (packages/core/src/auth.ts, validToken) validate the signature and exp only. None reference nbf.
Verified by reading all four implementations in source.
Reproduction
Mint a token with an nbf set a minute in the future, then verify it in each framework.
- Ruby: rejected, correctly, until
nbf passes
- Python, PHP, Node: accepted immediately
Why it matters
A token intended to become valid later is live immediately on three of the four frameworks. In a mixed-language estate the authentication decision depends on which service received the request, which is not a property anybody wants in an auth path.
nbf is a registered claim in RFC 7519 section 4.1.5. A verifier handed a claim it understands and then ignoring it is not doing what the caller expected.
Ruby already issues nbf on every token it mints, so tokens carrying the claim exist in the wild today.
Suggested fix
Python is master, so the decision gets made there first. Validating nbf in all four is the correct call, given Ruby already issues it.
The alternative, dropping nbf from Ruby's issuer, throws away a working RFC-conformant check to reach parity downward. Not recommended.
Needs the fix plus a named regression test in all four, positive and negative: a token with a past nbf accepted, a token with a future nbf rejected.
Found by
Auditing Auth across all four frameworks while grounding a course module on authentication. No fix applied.
Summary
Ruby issues and validates the JWT
nbf(not before) claim. Python, PHP and Node ignore it. The same token, with the same secret, gets two different answers depending on which framework verifies it.Where
Ruby, which is the correct one:
Python (
tina4_python/auth/__init__.py,valid_token), PHP (Tina4/Auth.php) and Node (packages/core/src/auth.ts,validToken) validate the signature andexponly. None referencenbf.Verified by reading all four implementations in source.
Reproduction
Mint a token with an
nbfset a minute in the future, then verify it in each framework.nbfpassesWhy it matters
A token intended to become valid later is live immediately on three of the four frameworks. In a mixed-language estate the authentication decision depends on which service received the request, which is not a property anybody wants in an auth path.
nbfis a registered claim in RFC 7519 section 4.1.5. A verifier handed a claim it understands and then ignoring it is not doing what the caller expected.Ruby already issues
nbfon every token it mints, so tokens carrying the claim exist in the wild today.Suggested fix
Python is master, so the decision gets made there first. Validating
nbfin all four is the correct call, given Ruby already issues it.The alternative, dropping
nbffrom Ruby's issuer, throws away a working RFC-conformant check to reach parity downward. Not recommended.Needs the fix plus a named regression test in all four, positive and negative: a token with a past
nbfaccepted, a token with a futurenbfrejected.Found by
Auditing
Authacross all four frameworks while grounding a course module on authentication. No fix applied.