panva / jose

JWA, JWS, JWE, JWT, JWK, JWKS for Node.js, Browser, Cloudflare Workers, Deno, Bun, and other Web-interoperable runtimes
MIT License
5.64k stars 316 forks source link

Sign then Verify Produce wrong expired time #719

Closed consciousnessdev closed 1 month ago

consciousnessdev commented 1 month ago

What happened?

When i try test Sign & Verify JWT with jest based on examples

it produce wrong expired date (1970-01-20 ...)

Version

5.9.2

Runtime

Node.js

Runtime Details

v20.15.0

Code to reproduce

import { SignJWT, jwtVerify } from 'jose';

it('Should returned token is valid', async () => {
  // Sign
  const secret = new TextEncoder().encode(
    'cc7e0d44fd473002f1c42167459001140ec6389b7353f8088f4d9a95f2f596f2'
  );
  const alg = 'HS256';
  const jwt = await new SignJWT({ 'urn:example:claim': true })
  .setProtectedHeader({ alg })
  .setIssuedAt(new Date())
  .setIssuer('urn:example:issuer')
  .setAudience('urn:example:audience')
  .setExpirationTime('2hr')
  .sign(secret);

  // Verify
  const { payload } = await jwtVerify(jwt, secret, {
    issuer: 'urn:example:issuer',
    audience: 'urn:example:audience'
  });

  if (payload.exp) {
    const today = new Date().getTime();
    const expiredDate = payload.exp;

    console.log('DEBUG EXPIRED DATE', new Date(payload.exp)) // output: DEBUG EXPIRED DATE 1970-01-20T23:38:19.149Z

    // isValid is check if expiredDate miliseconds greather than today milliseconds
    const isValid = expiredDate > today
    expect(isValid).toBe(true) // returned false
  }
});

Required

Expected

panva commented 1 month ago

Hi @consciousnessdev

These are correct NumericDate values as per RFC 7519^jwt. NumericDate is seconds since UNIX epoch, whereas the Date constructor value argument is milliseconds since UNIX epoch.

NumericDate
      A JSON numeric value representing the number of seconds from
      1970-01-01T00:00:00Z UTC until the specified UTC date/time,
      ignoring leap seconds.