Short answer
Do not store the ID token. Call getIdToken() on the current user right before each request; the SDK returns the cached token and refreshes it when it has expired. On the server, answer auth/id-token-expired with a 401, and let the client retry once with getIdToken(true).
Why the token is expired, and the fix
01
The app reuses a token it saved earlier
“Firebase ID tokens are short lived and last for an hour; the refresh token can be used to retrieve new ID tokens.” Firebase, Manage user sessions
The usual cause: the token was read once after sign-in and put in state, localStorage or an API client’s default header. Ask the SDK for it on every request instead.
async function api(path, init = {}) { const token = await auth.currentUser.getIdToken(); return fetch(path, { ...init, headers: { ...init.headers, Authorization: `Bearer ${token}` }, }); }02
The server error is not handled
“The provided Firebase ID token is expired.” Firebase, Admin Authentication API errors (auth/id-token-expired)
verifyIdToken rejects an expired token with this code. Return 401 instead of 500, so the client knows to get a new token and retry once.
try { const decoded = await getAuth().verifyIdToken(idToken); req.uid = decoded.uid; } catch (e) { if (e.code === 'auth/id-token-expired') return res.status(401).end(); throw e; }03
Force a refresh after a 401
Passing true makes the SDK fetch a new token even if its cached one looks valid. Use it for the one retry, not on every call.
const token = await auth.currentUser.getIdToken(/* forceRefresh */ true);04
The server clock is off
If every token fails, even fresh ones, check the server’s clock. A server clock that runs far ahead, past the token’s expiry time, makes valid tokens look expired. A device with a wrong clock can also hand out a stale token. Turn on automatic time sync.
05
A long-lived connection kept the first token
A WebSocket, server-sent events stream or GraphQL subscription that sent the token once at connect time is still using it an hour later. Send a fresh token on each reconnect, or re-authenticate the connection before the hour is up.
06
Revoked is a different error
“If the user's token is revoked, the user should be signed out on the client or asked to reauthenticate” Firebase, Manage user sessions (Detect ID token revocation)
With checkRevoked set, a token whose refresh token was revoked fails with auth/id-token-revoked. That one needs the person to sign in again, not a refresh.
Checked against the vendor’s docs on : Firebase docs: Manage user sessions; Firebase docs: Verify ID tokens; Firebase docs: Admin Authentication API errors.
Rather hand it over?
Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.
- from $450App Fix TicketOne reproducible bug in an existing mobile or web app, diagnosed and fixed.See scope and start
- from $450AI-Built App RescueA Lovable, Bolt or Cursor app checked end to end in 3 days, then its worst problems fixed at a fixed price.No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.See scope and start
Related: Firebase auth/user-disabled · Firebase auth/requires-recent-login · Supabase “JWT expired” · Firebase “FIS_AUTH_ERROR”