Skip to content

jwt.verify() returns numeric payload claims as strings #1042

Open

Description

@The-FirstMoon

Explanation:
I hope you doing great guys
When I use "verify()" in Typescript it is going to return string for everything even the one was a number in the "sign()" object payload.

Summary of the issue:
When signing a JWT with a numeric id claim, jwt.verify() appears to return the claim as a string instead of a number.

A small copy of my code:
const token = jwt.sign(
{ id: 67 },
secret
);
const decoded = jwt.verify(token, secret) as { id: number };
console.log(typeof decoded.id);
Expected behavior:
number
Actual behavior:
string

I checked the value before calling "jwt.sign()" and was confirmed to be a number .

Environment
Node.js: v20.20.2
Package: [jsonwebtoken, @types/jsonwebtoken]
Package version: [^9.0.3, ^9.0.10]
OS: window 11

I hope you have a great day.

Activity

  1. official-burak commented on Aug 27, 2026

    @official-burak

    jwt.verify() does not stringify numeric claims. The payload is JSON.stringify on sign and JSON.parse on verify, so a JSON number stays a number.

    I ran this on jsonwebtoken@9.0.3 (same major as yours):

    const jwt = require('jsonwebtoken');
    const decoded = jwt.verify(jwt.sign({ id: 67 }, 's'), 's');
    console.log(typeof decoded.id, decoded.id); // number 67

    The payload segment is {"id":67,...} with an unquoted number. @types/jsonwebtoken's JwtPayload also does not declare id, so as { id: number } is only a type assertion. It cannot turn a runtime number into a string.

    If you are actually seeing a string, id was almost certainly already a string before sign. Typical sources: HTML form fields, query params, process.env, Mongo ObjectId via .toString(), or spreading a parsed JSON body that quoted the value. Log typeof payload.id immediately before jwt.sign.

    Do not confuse id with registered string claims. sub / jti are strings by spec. iat / exp / nbf are numbers.

    If you paste the compact token (or just the middle payload segment, decoded) we can tell which of those it is.

  2. Ameer77-tech commented on Oct 26, 2026

    @Ameer77-tech

    node - v23.11.0, jsonwwebtoken@9.0.3

    const token = jwt.sign(
    { id: 67 },
    "secret"
    );
    const decoded = jwt.verify(token, "secret")
    console.log(typeof decoded.id);
    

    output:
    number

    I don't see an issue here, maybe once check for yourself

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions