Authentication and application access
Firebase login works. Why does my API still return 401?
The Google popup closes. Your name appears in the navbar. You open the dashboard and get 401 Unauthorized from your own API.
I'd open the failed request in the Network panel before touching the login button again. The Firebase SDK can have a signed-in user while an ordinary fetch sends no identity to your server. The missing piece can be one header.
Look at the request after login
Find the request that returned 401 and inspect its headers. For a backend that accepts Firebase ID tokens, you should see Authorization: Bearer .... Then check the response body. An application error such as sign_in_required tells you more than the red status number.
Firebase's token verification guide describes the connection: get the signed-in user's ID token in the browser, send it to your backend, and verify it there. Watch the token type if you've just integrated Google sign-in. Google's access token and Firebase's ID token have different jobs, and it's easy to pass along the wrong value.
Here's the request for Helpful Mods Foundation Kit's session endpoint, using the app's initialized browser auth instance:
import { getIdToken } from "firebase/auth";
const user = auth.currentUser;
if (!user) throw new Error("Sign in before checking the session.");
const response = await fetch("/api/session", {
headers: { Authorization: `Bearer ${await getIdToken(user, true)}` },
credentials: "same-origin",
});
if (!response.ok) {
throw new Error(`Session check failed: ${response.status}`);
}
Use your own protected endpoint if you're debugging another app. The true asks Firebase for a fresh token, which is useful when investigating stale identity. Foundation's normal requests let the SDK manage token refresh.
If the browser sends the header and the server doesn't receive it, you've narrowed the problem to the proxy or middleware between them. Follow that request through instead of adding another sign-in attempt.
A valid token can belong to the wrong project
This one is easy to miss after a deployment. The browser was built with staging's Firebase configuration, while the API expects production. Google happily signs the user into staging. Your production server then rejects the token because its audience belongs to another project.
Compare the deployed browser's project ID with the server's expected project. Check the actual build that customers load; editing a local environment file won't change JavaScript you've already published. Foundation verifies the token's signature, issuer and project audience before looking up the current account.
An expired or revoked session needs a different fix. Get a fresh ID token for expiry; ask the user to sign in again when the session has been revoked. Firebase documents those states in its Admin error reference and session management guide.
Read the application error too
In Foundation, these responses point to specific parts of the request:
| Error | Where I'd look |
|---|---|
401 sign_in_required | Missing or malformed bearer header. |
401 invalid_identity_token | Expiry, signature, issuer or project mismatch. |
403 verified_email_required | Email verification and the current user/token state. |
403 same_origin_required | The browser origin, public hostname, proxy and APP_ORIGIN. |
503 identity_state_unavailable | The provider lookup or network connection used to check the current account. |
Email verification is worth checking when the user says, "But I just clicked the link." The original tab may still hold the older user state and token. Reload the Firebase user and refresh the ID token after verification, then retry the failed request.
Once identity passes, follow the workspace permission check. Someone can be signed into the correct account and still be opening a workspace they haven't joined. The useful debugging question becomes which membership the backend resolved for that account.
Connecting a mod to an existing app
Standalone Helpful Mods services accept a scoped token created by your trusted backend. Your backend verifies the existing app session, maps the user to a stable actor ID, and signs the mod token. That lets you keep the authentication system your app already uses. A raw Firebase ID token sent straight to the standalone Teams endpoint won't match that contract.
The coding-agent installation guide follows that connection through the app's existing sign-in, backend and mod service.
After correcting the connection, reload the dashboard and repeat the action that originally failed. That catches the common case where the first request works but the next page still uses an older API helper.
Foundation Kit includes Firebase sign-in, server verification, workspace permissions and billing already connected. Paid Membership and Teams brings the team feature into an existing app through its backend.