You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
jwt.verify() returns numeric payload claims as strings #1042
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 .
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):
constjwt=require('jsonwebtoken');constdecoded=jwt.verify(jwt.sign({id: 67},'s'),'s');console.log(typeofdecoded.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.
Activity
official-burak commentedon Aug 27, 2026
jwt.verify()does not stringify numeric claims. The payload isJSON.stringifyon sign andJSON.parseon verify, so a JSON number stays a number.I ran this on
jsonwebtoken@9.0.3(same major as yours):The payload segment is
{"id":67,...}with an unquoted number.@types/jsonwebtoken'sJwtPayloadalso does not declareid, soas { id: number }is only a type assertion. It cannot turn a runtime number into a string.If you are actually seeing a string,
idwas almost certainly already a string beforesign. Typical sources: HTML form fields, query params,process.env, MongoObjectIdvia.toString(), or spreading a parsed JSON body that quoted the value. Logtypeof payload.idimmediately beforejwt.sign.Do not confuse
idwith registered string claims.sub/jtiare strings by spec.iat/exp/nbfare numbers.If you paste the compact token (or just the middle payload segment, decoded) we can tell which of those it is.
Ameer77-tech commentedon Oct 26, 2026
node - v23.11.0, jsonwwebtoken@9.0.3
output:
number
I don't see an issue here, maybe once check for yourself