gladly-team / next-firebase-auth

Simple Firebase authentication for all Next.js rendering strategies
https://nfa-example-git-v1x-gladly-team.vercel.app/
MIT License
1.34k stars 291 forks source link

Updated claims not immediately reflected in the authUser object #589

Closed madhurjain closed 1 year ago

madhurjain commented 1 year ago

Describe the bug Updated Custom Claims are not immediately reflected in the client-side authUser object obtained using the useAuthUser() hook

Versions next-firebase-auth version: 1.0.0-canary.9 Firebase JS SDK: 9.11.0 Next.js: 12.1.4

To Reproduce Steps to reproduce the behavior:

  1. Update the user's claims object directly in Firebase using Admin SDK, etc
  2. In a nextjs app, retrieve authUser using the useAuthUser() hook and dump the object to console
  3. Check the value of claims:
  4. It should reflect the updated value but it shows the previously cached value until user logout / login or for ~1 hr

Expected behavior I am using custom claims to store if a user is a paid (premium) user. The custom claims are updated directly by Stripe via Webhook call once the customer successfully makes a payment using Stripe Checkout. I expect that this information is reflected in the authUser object obtained using the useAuthUser() hook when the user is re-directed to my app (app reload). But I keep seeing the old custom claims for about an hour or until the user logs-out and logs back in.

Debug and error logs No errors reported

Additional context On page reload, I can see a POST request made to https://identitytoolkit.googleapis.com/v1/accounts:lookup?key=xyz URL and the response contains the updated custom claim but this is not reflected in the authUser object obtained using the useAuthUser() hook.

madhurjain commented 1 year ago

I looked at #250, #286, #301 and applied a temporary fix of force refreshing a token by calling

const authUser = useAuthUser();
// force refresh authUser token
authUser.getIdToken(true);

This kinda solves the issue for now, but this shouldn't be required, isn't it?

kmjennison commented 1 year ago

This is expected Firebase behavior. From docs:

After new claims are modified on a user via the Admin SDK, they are propagated to an authenticated user on the client side via the ID token in the following ways:

  • A user signs in or re-authenticates after the custom claims are modified. The ID token issued as a result will contain the latest claims.
  • An existing user session gets its ID token refreshed after an older token expires.
  • An ID token is force refreshed by calling currentUser.getIdToken(true).

My recommendation is to see if there's a natural event on your client app to force a refresh; for example, after a user modifies their subscription. Forcing a token refresh every time isn't ideal but will get the job done.