firebase / firebase-admin-node

Firebase Admin Node.js SDK
https://firebase.google.com/docs/admin/setup
Apache License 2.0
1.63k stars 371 forks source link

[FR] Allow custom caching of public keys when verifying JWTs #1158

Closed lazerwalker closed 3 years ago

lazerwalker commented 3 years ago

Is your feature request related to a problem? Please describe. I'm using Firebase auth with a SPA and my own backend services. My backend is a series of serverless functions hosted on a provider other than Firebase/GCP.

Currently, when the auth FirebaseTokenVerifier fetches the Firebase public keys, it caches them just by storing them in-memory in the JS process by setting them on the current FirebaseTokenVerifier object (see https://github.com/firebase/firebase-admin-node/blob/01d8177650676a142474229538f0b469fc363a65/src/auth/token-verifier.ts#L287).

However, since I'm running my server code as a bunch of serverless functions rather than a persistent server process, this means that I will never have cached public keys (or at least, I need to assume I never will). For my specific use case, the latency hit of making that HTTP request on every single server API request is unacceptable; I need a way to properly cache the result of that public key HTTP request across my various serverless function request instances.

Describe the solution you'd like

I'd like some way to specify either my own caching strategy or my own fetching function for getting and storing Google public keys. I have no strong thoughts on what this should look like, given the code is all currently private to the module.

One potential solution: make FirebaseTokenVerifier.publicKeys and FirebaseTokenVerifier.publicKeysExpireAt public, so I could manually manage making the HTTP requests myself and then just inject the final results into the existing flow / FirebaseTokenVerifier object. I don't think this would require any other framework changes.

Describe alternatives you've considered

My current plan of action is to avoid using this library entirely and manage the entire JWT verification process using a third-party library. I appreciate that https://firebase.google.com/docs/auth/admin/verify-id-tokens#web includes clear instructions to do so, but this seems like a shame given I'm using a language (JS) you officially support.

Alternatively, if I understand JWTs correctly, I can theoretically manage this at the application layer by caching the token itself: verify it once, store it in a cache (I have a Redis instance already), and future requests can compare the newly-received token against that known-validated token instead of validating every request. This seems unnecessarily complex, and risks user implementation error.

google-oss-bot commented 3 years ago

I found a few problems with this issue:

hiranya911 commented 3 years ago

Alternatively, if I understand JWTs correctly, I can theoretically manage this at the application layer by caching the token itself

Implementing an app-level token cache is the recommended solution for this situation, and it's usually much simpler than implementing a public key cache for our SDK:

  1. It doesn't require any API changes in the SDK, nor requires any knowledge about how our SDK is implemented.
  2. JWTs have an expiry time encoded into them, which serves as a natural expiry time for the cache entries.
  3. It's also more performant, since you can bypass the JWT token verification step entirely for tokens that have already been verified.
lazerwalker commented 3 years ago

Thanks for the response!