Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export interface JWTPayloadSpec {
*
* @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.4 RFC7519#section-4.1.4}
*/
exp?: number
exp?: number | string
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Critical: Type/validator mismatch will cause runtime validation failures.

The TypeScript type now allows exp to be number | string, but the validator schema at line 221 only accepts t.Number(). When users pass a string value for exp and schema validation is enabled, the validator will reject it at runtime, causing validation errors.

Additionally, per RFC 7519 section 4.1.4, the exp claim in the final JWT payload must be a NumericDate (numeric value representing seconds since epoch). While jose's setExpirationTime() accepts time-span strings like '1h' as input for convenience, it converts them to numeric timestamps before encoding them into the JWT.

Since JWTPayloadSpec represents the structure of the JWT payload (as stated in its JSDoc comment at lines 39-46), it should match the RFC 7519 specification where exp is always numeric. The JWTPayloadInput interface (line 122) correctly allows string | number for input flexibility.

Recommendation:

  1. Revert JWTPayloadSpec.exp back to number only (RFC-compliant)
  2. Keep JWTPayloadInput.exp as string | number (already correct at line 122)
  3. The existing implementation at lines 350-352 is correct and doesn't need changes

This maintains the distinction between input types (flexible) and payload types (RFC-compliant).

-	exp?: number | string
+	exp?: number

Run the following script to verify how jose handles string exp values and confirm the validator mismatch:

Additionally, please search for the RFC 7519 specification on the exp claim type:


🏁 Script executed:

#!/bin/bash
# Verify the validator schema for exp claim
echo "=== Validator schema for exp (should be t.Number()) ==="
rg -n "exp.*t\.(Optional|Number)" src/index.ts

echo ""
echo "=== All references to JWTPayloadSpec ==="
rg -n "JWTPayloadSpec" --type ts

echo ""
echo "=== Check if setExpirationTime is called with exp ==="
rg -n -A2 "setExpirationTime" src/index.ts

Length of output: 665


🌐 Web query:

RFC 7519 JWT exp claim type specification NumericDate

💡 Result:

Short answer — what NumericDate is and how exp uses it:

  • NumericDate = number of seconds (not milliseconds) since 1970-01-01T00:00:00Z UTC, ignoring leap seconds; it may be an integer or a non‑integer (fractional seconds). [1]
  • The "exp" claim’s value MUST be a number containing a NumericDate. The JWT MUST NOT be accepted if the current time is at or after that NumericDate; implementations MAY allow a small clock‑skew leeway (usually a few minutes). [1][2]

Sources:
[1] RFC 7519 (NumericDate definition and "exp" processing).
[2] Practical clarification (e.g., community/implementation notes confirming seconds, not milliseconds).


Revert JWTPayloadSpec.exp to number only (align with validator & RFC-compliant)

The interface in src/index.ts:89 was widened to number | string, but the runtime schema (line 221: t.Optional(t.Number())) only accepts numbers and RFC 7519 mandates exp be a NumericDate number. Keep JWTPayloadInput.exp as string|number for input flexibility and revert the payload spec:

-	exp?: number | string
+	exp?: number
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
exp?: number | string
++ b/src/index.ts
@@ -86,7 +86,7 @@
// ... other fields in JWTPayloadSpec ...
exp?: number
// ... remaining fields ...
🤖 Prompt for AI Agents
In src/index.ts around line 89, revert JWTPayloadSpec.exp to type number only
(remove the union with string) so the interface matches the runtime schema at
~line 221 (t.Optional(t.Number())) and RFC 7519; keep JWTPayloadInput.exp as
string|number for input parsing elsewhere if present. Update the type
declaration at line 89 from `exp?: number | string` to `exp?: number`, and
ensure any downstream usages or validators expect a NumericDate (number) rather
than a string.


/**
* JWT Issued At
Expand Down