finsweet/fireworkers

JWT's generated are invalid

Closed this issue · 5 comments

Hi, thanks for this library! It's helped a lot :)

I noticed however, the JWT's generated by the init function are invalid, notably that they have an iat of 0 and exp of 3600.

Notably,

const db = await Firestore.init({
    uid: 'anything',
    project_id: authConfig.projectId,
    client_email: serviceUser.client_email,
    private_key: serviceUser.private_key,
    private_key_id: serviceUser.private_key_id
})

const a = await Firestore.get(db, 'users')

Would return the following error:

{
  "error": {
    "code": 401,
    "message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
    "status": "UNAUTHENTICATED"
  }
}

I don't know enough about JOSE to help debug or fix the actual issue, but I was able to get the library working with a JWT I generate myself using @tsndr/cloudflare-worker-jwt (https://github.com/tsndr/cloudflare-worker-jwt):

const now = new Date().getTime() / 1000

const JWT = await jwt.sign({
    iss: serviceUser.client_email,
    sub: serviceUser.client_email,
    aud: "https://firestore.googleapis.com/",
    iat: now,
    exp: now + 3600,
}, serviceUser.private_key, {algorithm: "RS256"})

Passing this into my own DB object with the public key gives me better responses. Putting the two key's into jwt.io side by side reveals:

Firestore.init jwt.sign
image image

I'm happy to open a PR that replaces jose with @tsndr/cloudflare-worker-jwt if you're okay with the library change.

🤔 we're actively using fireworkers in our production environments and it works fine in our case, here's an example of a JWT:

image

I'll try to reproduce this issue again and get back to you

I also received the "Request had invalid authentication credentials" error (it worked properly with native libraries).

I also received the "Request had invalid authentication credentials" error (it worked properly with native libraries).

@mjaskolski Can you toss your JWT generated with Fireworkers into https://jwt.io/'s Decoder and share the body? Use my screenshots as a guidance of what is and isn't safe to share publicly. If it's related to this issue you'll have an iat of 0.

Soooo... Outside of fetch handlers, new Date() will return a 0-date...

If you are, like me, tempted to created the JWT on the top level, it will have this odd iat: 0 and exp: 3600.

Instead you'll have to create the JWT inside the fetch handler.
Personally I have my database abstraction make the JWT on-demand, and cache it.
(Also, check if before every request - I don't know how long cloudflare worker environment can persist, but I wouldn't be surprised if suddenly it lasts longer than an hour)

Hi,

I've recently come to learn that within a fetch handler, new Date() returns the time of the last IO, to prevent timing attacks. Outside a fetch handler, it (the current time) is zero.

So @dralletje's solution of moving the JWT creation into fetch is the correct solution. I'm not sure why my solution worked at all actually!

Closing this because Cloudflare is silly.