tsndr / cloudflare-worker-jwt

A lightweight JWT implementation with ZERO dependencies for Cloudflare Workers.
MIT License
649 stars 51 forks source link

[BUG] verify not working in 2.2.10 #49

Closed simcolin closed 10 months ago

simcolin commented 10 months ago

Was using version 2.2.3, everything works fine

updated to 2.2.10 and now the most basic example is not working

const token = await jwt.sign({ chroot: "chroot" }, jwtSecret);
console.log(await jwt.verify(token, jwtSecret)) // prints false

Tested locally with Node version 20.9.0 and deployed to cloudflare pages

If you need any more infos about the setup

rmarscher commented 10 months ago

I just noticed this too with trying to verify a supabase token using a string hs256 key. Maybe an issue with the base64 handling in the v2.0.8 refactor? Downgrading to 2.0.7 fixes it for me.

tsndr commented 10 months ago

Hey, thanks for letting me know, will do some testing myself and report back :)

tsndr commented 10 months ago

I've now created a test project: https://github.com/tsndr/jwt-test

And when depoying this to Cloudflare Workers it runs without any issues.

Here's the result:

{
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0IiwibW9yZSI6IkB0ZXN0IiwiaWF0IjoxNzAwMTM3MzUzfQ._yucoh2EkUExiPmI5ugUfxs-BAPpoyKmJ-MrHZdGq8Q",
  "decoded": {
    "header": null,
    "payload": {
      "sub": "test",
      "more": "@test",
      "iat": 1700137353
    }
  },
  "verified": true
}

If you can provide more context, so that I'm able to reproduce this error, I'll try to implement a fix.

simcolin commented 10 months ago

When I test your project (https://github.com/tsndr/jwt-test) it works

But if I remove the sub property from the jwt.sign payload, its broken. payload becomes null and verify return false

Here is the full code

const secret = 'super-secret'

const token = await jwt.sign({ more: '@test' }, secret)
console.log({ token }) // { token:  'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJtb3JlIjoiQHRlc3QiLCJpYXQiOjE3MDAxNDExMTd9.vBZIxVkxvXdpNc9tfmXQUHCpcDuJSVoMBNN6MbgBl2k' }

const decoded = jwt.decode(token)
console.log({ decoded }) // { decoded: { header: null, payload: null } }

const verified = await jwt.verify(token, secret)
console.log({ verified }) // { verified: false }

So the sub property seems mandatory for some reason, and was not before.

simcolin commented 10 months ago

While doing some tests I found a new weird behaviour.

for some reason if payload is { sub: "test" } the verification works but if payload is { sub: 'chroot' } the verification fails and decoded payload is null

tsndr commented 10 months ago

Got it, please try again with v2.3.0 :)

simcolin commented 10 months ago

2.3.0 fixes the issue for me, I just tested a few different payloads and they don't seem to impact decode or impact in a bad way.

Thank you for the fix !