Skip to content

nbf claim is validated in Ruby only, ignored by Python, PHP and Node #107

Description

@andrevanzuydam

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions