Answer
Firebase Auth for Flutter Web relies on the underlying Firebase JavaScript SDK, which silently refreshes the ID token in the background as long as the page remains loaded and has network connectivity. No manual call is required for routine refresh.
Confirmed facts
- The SDK refreshes the ID token when its remaining lifetime falls below a few minutes, using the stored refresh token via a REST call to
identitytoolkit.googleapis.com.
- This refresh is independent of the tab’s visibility state; it continues while the page is alive.
- Calling
FirebaseAuth.instance.currentUser?.getIdTokenResult() (without true) returns the current token and its expirationTime.
- Calling the same method with
true forces a server round‑trip to obtain a fresh ID token.
- Custom claims are never exposed to the client; any authorization based on them must be performed on a trusted backend.
Likely explanation / behavior when the tab is backgrounded
Because the refresh timer is driven by the SDK’s internal timeout, backgrounding the tab does not stop the timer. However, if the browser throttles or suspends timers (e.g., Chrome’s background throttling), the refresh attempt may be delayed until the tab regains focus or a timer fires. Once the page is visible again or the timer expires, the SDK will still attempt the refresh, provided the page has not been unloaded and network is available.
Steps to detect and handle token expiration client‑side
- When the app starts or after any auth change, call
currentUser?.getIdTokenResult() to read expirationTime (a Unix millisecond timestamp).
- Calculate the time remaining (
expirationTime - Date.now()). If it is less than, for example, 5 minutes, schedule a refresh.
- To obtain a fresh token without forcing a full re‑auth, call
getIdTokenResult(true). This returns a new ID token and updates the internal cache.
- Optionally listen to
FirebaseAuth.instance.authStateChanges() to detect sign‑out or token‑clear events.
- If a forced refresh fails (e.g., network error), redirect the user to the sign‑in flow.
Least‑privilege enforcement
Since custom claims cannot be read client‑side, the Flutter app must rely on the backend to verify the ID token and return scoped data or permissions. The client can still enforce UI‑level restrictions based on roles received from the server, but any security‑critical decision must be validated server‑side.
Missing diagnostic detail: Please confirm whether your app uses the default Firebase persistence (local/session storage) or a custom persistence mechanism. If persistence is disabled or cleared, the background refresh will not work and you will need to manage token renewal manually.