# Auth State, ID Tokens and Custom Claims — Firebase

Source: https://www.skillbyai.com/en/firebase/au-state

> Knowing who is signed in, everywhere.

## Listeners, tokens and claims

Sign-in state is restored asynchronously when the page loads, so do not read `auth.currentUser` once at startup; subscribe with **`onAuthStateChanged`** and render based on the user it delivers. Each signed-in user has a short-lived **ID token** (a JWT, refreshed automatically by the SDK) that Firebase services verify; you can send it to your own backend and verify it with the Admin SDK (`verifyIdToken`). **Custom claims** are small key-value pairs (such as `{ admin: true }`) set only from trusted code with the Admin SDK; they appear in the token and in rules as `request.auth.token`. Claims are size-limited (check the docs) and reach the client only after the token refreshes.

## Listening for the user and reading claims

Client and Admin SDK, TypeScript.

```typescript
// client
import { getAuth, onAuthStateChanged } from "firebase/auth";

const auth = getAuth(app);
onAuthStateChanged(auth, async (user) => {
  if (!user) return showSignIn();
  const result = await user.getIdTokenResult(); // pass true to force a refresh
  showApp({ uid: user.uid, isAdmin: result.claims.admin === true });
});

// trusted server code (Cloud Function or your backend)
import { getAuth as getAdminAuth } from "firebase-admin/auth";

export async function makeAdmin(uid: string) {
  await getAdminAuth().setCustomUserClaims(uid, { admin: true });
  // the user sees the claim after their ID token refreshes
}
```

## Claims are for roles, not profiles

Keep claims tiny (roles, tenant id). Store profile data such as names and preferences in Firestore.

**Quiz:** Where can custom claims be set?

- [ ] In the web config object
- [ ] From any client with updateProfile
- [ ] Inside Security Rules
- [x] Only from trusted code using the Admin SDK

*Answer:* Only from trusted code using the Admin SDK. Clients must not grant themselves roles.
