Skip to main content
Technology & EngineeringAuth Services233 lines

Firebase Auth

Build with Firebase Authentication for user sign-in. Use this skill when the project needs to integrate Firebase Auth for email/password, Google, GitHub, Apple, phone OTP, anonymous auth, custom tokens, or ID token verification. Covers the Firebase Auth SDK (v9+), providers, auth state, custom claims, and server-side verification.

Quick Summary33 lines
You are an auth specialist who integrates Firebase Authentication into projects.
Firebase Auth provides drop-in authentication with email/password, social
providers, phone auth, and anonymous auth — with client SDKs and server-side
token verification via the Admin SDK.

## Key Points

- Use `onAuthStateChanged` for reactive auth state — don't check `currentUser` directly on load
- Verify ID tokens server-side for API routes — never trust client-side auth alone
- Use custom claims for authorization (admin, plan, roles) — they're embedded in the token
- Force token refresh after setting custom claims — tokens are cached for up to 1 hour
- Use `signInWithRedirect` on mobile — popups are blocked on many mobile browsers
- Clean up auth state listeners in useEffect return functions
- Trusting `auth.currentUser` on page load — it's null until auth initializes
- Not verifying ID tokens server-side — client tokens can be spoofed
- Storing sensitive data in custom claims — they're visible in the JWT
- Using custom claims for frequently changing data — token refresh is needed
- Not handling the loading state — auth state takes a moment to initialize
- Creating custom session management when Firebase handles token refresh

## Quick Example

```bash
npm install firebase
npm install firebase-admin  # Server-side
```

```typescript
import { signOut } from 'firebase/auth';
await signOut(auth);
```
skilldb get auth-services-skills/firebase-authFull skill: 233 lines
Paste into your CLAUDE.md or agent config

Firebase Authentication Integration

You are an auth specialist who integrates Firebase Authentication into projects. Firebase Auth provides drop-in authentication with email/password, social providers, phone auth, and anonymous auth — with client SDKs and server-side token verification via the Admin SDK.

Core Philosophy

Client-side first

Firebase Auth runs primarily on the client. The SDK handles the OAuth flows, token refresh, and auth state persistence. Your server verifies ID tokens but doesn't manage sessions — Firebase handles that automatically.

Provider-agnostic

Firebase Auth supports email/password, Google, Apple, GitHub, Twitter, Facebook, phone OTP, and anonymous auth through a consistent API. Adding a provider is enabling it in the console and adding a few lines of code.

Custom claims for authorization

Firebase Auth handles authentication (who is this user). For authorization (what can they do), set custom claims on the user token — admin, plan, orgId — and check them client-side or in security rules.

Setup

Install

npm install firebase
npm install firebase-admin  # Server-side

Initialize (client)

import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';

const app = initializeApp({
  apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
  authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
  projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
});

export const auth = getAuth(app);

Initialize (server)

import { initializeApp, cert } from 'firebase-admin/app';
import { getAuth } from 'firebase-admin/auth';

const app = initializeApp({
  credential: cert({
    projectId: process.env.FIREBASE_PROJECT_ID,
    clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
    privateKey: process.env.FIREBASE_PRIVATE_KEY?.replace(/\\n/g, '\n'),
  }),
});

export const adminAuth = getAuth(app);

Key Techniques

Email/password auth

import { createUserWithEmailAndPassword, signInWithEmailAndPassword, updateProfile } from 'firebase/auth';

// Sign up
const { user } = await createUserWithEmailAndPassword(auth, email, password);
await updateProfile(user, { displayName: name });

// Sign in
const { user } = await signInWithEmailAndPassword(auth, email, password);

// Password reset
import { sendPasswordResetEmail } from 'firebase/auth';
await sendPasswordResetEmail(auth, email);

OAuth providers

import {
  signInWithPopup, signInWithRedirect, getRedirectResult,
  GoogleAuthProvider, GithubAuthProvider, OAuthProvider
} from 'firebase/auth';

// Google
const googleProvider = new GoogleAuthProvider();
const { user } = await signInWithPopup(auth, googleProvider);

// GitHub
const githubProvider = new GithubAuthProvider();
const { user } = await signInWithPopup(auth, githubProvider);

// Apple
const appleProvider = new OAuthProvider('apple.com');
appleProvider.addScope('email');
const { user } = await signInWithPopup(auth, appleProvider);

// Redirect flow (mobile-friendly)
await signInWithRedirect(auth, googleProvider);
// On page load:
const result = await getRedirectResult(auth);
if (result) {
  const user = result.user;
}

Auth state listener

import { onAuthStateChanged, type User } from 'firebase/auth';

// React context pattern
function AuthProvider({ children }: { children: React.ReactNode }) {
  const [user, setUser] = useState<User | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      setUser(user);
      setLoading(false);
    });
    return unsubscribe;
  }, []);

  return (
    <AuthContext.Provider value={{ user, loading }}>
      {children}
    </AuthContext.Provider>
  );
}

ID token verification (server-side)

// API route — verify Firebase ID token
export async function GET(req: Request) {
  const authHeader = req.headers.get('authorization');
  if (!authHeader?.startsWith('Bearer ')) {
    return new Response('Unauthorized', { status: 401 });
  }

  const token = authHeader.split('Bearer ')[1];

  try {
    const decoded = await adminAuth.verifyIdToken(token);
    const userId = decoded.uid;

    const data = await db.query.posts.findMany({
      where: eq(posts.authorId, userId),
    });

    return Response.json(data);
  } catch {
    return new Response('Invalid token', { status: 401 });
  }
}

// Client-side — send token with requests
const token = await auth.currentUser?.getIdToken();
const res = await fetch('/api/posts', {
  headers: { Authorization: `Bearer ${token}` },
});

Custom claims

// Server-side: set custom claims
await adminAuth.setCustomUserClaims(userId, {
  admin: true,
  plan: 'pro',
  orgId: 'org_123',
});

// Client-side: read custom claims
const token = await auth.currentUser?.getIdTokenResult();
const isAdmin = token?.claims.admin === true;
const plan = token?.claims.plan as string;

// Force token refresh to get updated claims
await auth.currentUser?.getIdToken(true);

Phone auth

import { signInWithPhoneNumber, RecaptchaVerifier } from 'firebase/auth';

// Set up reCAPTCHA
const recaptcha = new RecaptchaVerifier(auth, 'recaptcha-container', {
  size: 'invisible',
});

// Send verification code
const confirmationResult = await signInWithPhoneNumber(auth, '+1234567890', recaptcha);

// Verify code
const { user } = await confirmationResult.confirm(userEnteredCode);

Sign out

import { signOut } from 'firebase/auth';
await signOut(auth);

Best Practices

  • Use onAuthStateChanged for reactive auth state — don't check currentUser directly on load
  • Verify ID tokens server-side for API routes — never trust client-side auth alone
  • Use custom claims for authorization (admin, plan, roles) — they're embedded in the token
  • Force token refresh after setting custom claims — tokens are cached for up to 1 hour
  • Use signInWithRedirect on mobile — popups are blocked on many mobile browsers
  • Clean up auth state listeners in useEffect return functions

Anti-Patterns

  • Trusting auth.currentUser on page load — it's null until auth initializes
  • Not verifying ID tokens server-side — client tokens can be spoofed
  • Storing sensitive data in custom claims — they're visible in the JWT
  • Using custom claims for frequently changing data — token refresh is needed
  • Not handling the loading state — auth state takes a moment to initialize
  • Creating custom session management when Firebase handles token refresh

Install this skill directly: skilldb add auth-services-skills

Get CLI access →

Related Skills

Hanko

Integrate Hanko for modern, passwordless authentication in your web applications. Use Hanko to leverage passkeys (FIDO2), magic links, and email OTP for strong, developer-friendly auth experiences. This skill covers embedding Hanko's UI, handling authentication events, and server-side token verification.

Auth Services231L

Kinde

Build with Kinde for authentication and user management. Use this skill when the project needs to integrate Kinde for sign-up, sign-in, OAuth, feature flags, organizations, roles and permissions, or a developer-friendly auth platform with generous free tier. Covers the Kinde Next.js SDK, server/client auth, organizations, feature flags, and webhooks.

Auth Services261L

Logto

Logto is an open-source, managed identity service that simplifies authentication and authorization for your applications. Use Logto when you need a robust, scalable, and developer-friendly solution for user management, single sign-on (SSO), and API protection, supporting OIDC and OAuth 2.0.

Auth Services298L

Lucia

Build with Lucia for lightweight, self-hosted authentication. Use this skill when the project needs a minimal, dependency-free auth library for session management, OAuth, password hashing, and database-backed sessions without vendor lock-in. Covers Lucia v3, session management, OAuth via Arctic, password auth, and database adapters.

Auth Services320L

Nextauth

Build with NextAuth.js (Auth.js) for authentication in Next.js and other frameworks. Use this skill when the project needs self-hosted auth with OAuth providers, credentials, magic links, database sessions, JWT, callbacks, or middleware protection. Covers Auth.js v5, providers, adapters, callbacks, middleware, and session management.

Auth Services321L

Ory Kratos

Integrate Ory Kratos as a self-sovereign, API-first identity and user management system. Use this skill when you need a robust, scalable, and secure solution for user registration, login, profile management, and session handling in modern web applications, SPAs, or microservices, without building core identity flows from scratch.

Auth Services333L