To sign out a user in Firebase, call signOut() from the firebase/auth module. This clears the local authentication state and triggers the onAuthStateChanged listener with a null user. After sign-out, redirect the user to your login page and clear any cached application state. The signOut function returns a Promise that resolves when the local session is fully cleared.
Signing Out a User in Firebase Authentication
Signing out a user in Firebase involves calling the signOut() function, handling the resulting auth state change, clearing any cached user data in your application, and redirecting to a public page. This tutorial covers the complete sign-out flow including error handling, auth state listeners, React component integration, and best practices for cleaning up application state after logout.
Prerequisites
- A Firebase project with Authentication enabled
- Firebase SDK installed in your project (npm install firebase)
- Users who can sign in (email/password, Google, or any provider)
- Basic understanding of React or your frontend framework
Step-by-step guide
Import signOut and call it from your auth instance
Import signOut and call it from your auth instance
Import the signOut function from firebase/auth and your auth instance from your Firebase configuration file. Call signOut(auth) which returns a Promise. The function clears the user's session from local storage (IndexedDB) and invalidates the current ID token. Handle errors in a try/catch block since signOut can fail if there is a network issue, though the local session is still cleared in most cases.
1import { getAuth, signOut } from 'firebase/auth';2import { app } from './firebase'; // your Firebase app instance34const auth = getAuth(app);56async function handleSignOut() {7 try {8 await signOut(auth);9 console.log('User signed out successfully');10 // Redirect to login page11 window.location.href = '/login';12 } catch (error) {13 console.error('Sign out error:', error);14 }15}Expected result: The user's local auth session is cleared. The onAuthStateChanged listener fires with a null user.
Listen for sign-out events with onAuthStateChanged
Listen for sign-out events with onAuthStateChanged
Set up an onAuthStateChanged listener in your app's root component to detect when the user's auth state changes. When the user signs out, the callback fires with null as the user parameter. Use this centralized listener to clear application state, reset stores, and redirect to the login page. This approach catches sign-outs from any trigger including token expiration and manual sign-out.
1import { getAuth, onAuthStateChanged } from 'firebase/auth';23const auth = getAuth(app);45onAuthStateChanged(auth, (user) => {6 if (user) {7 // User is signed in8 console.log('Signed in as:', user.email);9 } else {10 // User is signed out11 console.log('User signed out');12 // Clear any cached user data13 localStorage.removeItem('userProfile');14 sessionStorage.clear();15 }16});Expected result: The auth state listener fires whenever the user signs in or out, allowing centralized state management.
Build a sign-out button component in React
Build a sign-out button component in React
Create a reusable React component that handles the sign-out flow with loading state and error handling. The component disables the button during the async operation to prevent double clicks. After successful sign-out, redirect using window.location.href for a full page reload that clears all in-memory JavaScript state.
1import { useState } from 'react';2import { getAuth, signOut } from 'firebase/auth';34export function SignOutButton() {5 const [loading, setLoading] = useState(false);6 const [error, setError] = useState<string | null>(null);78 async function handleSignOut() {9 setLoading(true);10 setError(null);1112 try {13 const auth = getAuth();14 await signOut(auth);15 window.location.href = '/login';16 } catch (err) {17 setError('Failed to sign out. Please try again.');18 setLoading(false);19 }20 }2122 return (23 <div>24 <button onClick={handleSignOut} disabled={loading}>25 {loading ? 'Signing out...' : 'Sign out'}26 </button>27 {error && <p style={{ color: 'red' }}>{error}</p>}28 </div>29 );30}Expected result: A functional sign-out button that shows loading state, handles errors, and redirects after successful logout.
Clear application state after sign-out
Clear application state after sign-out
When a user signs out, you must clean up any user-specific data stored outside of Firebase Auth. This includes localStorage keys, sessionStorage, state management stores (Redux, Zustand), and any in-memory caches. Failing to clear this data can cause the next user who logs in to see stale data from the previous user.
1import { getAuth, signOut } from 'firebase/auth';23async function fullSignOut() {4 const auth = getAuth();56 // 1. Sign out from Firebase7 await signOut(auth);89 // 2. Clear application-specific storage10 const appKeys = ['userProfile', 'userSettings', 'cart', 'draftData'];11 appKeys.forEach((key) => localStorage.removeItem(key));12 sessionStorage.clear();1314 // 3. Reset state management store (example with Zustand)15 // useStore.getState().reset();1617 // 4. Full page redirect to clear in-memory state18 window.location.href = '/login';19}Expected result: All user-specific data is cleared from local storage, session storage, and state management. The app redirects to the login page with a clean state.
Handle sign-out in a React context provider
Handle sign-out in a React context provider
For applications with a centralized auth context, add the sign-out function to your context so any component can trigger logout. This pattern keeps auth logic in one place and provides the sign-out function through React context rather than importing Firebase directly in every component.
1import { createContext, useContext, useEffect, useState } from 'react';2import { getAuth, onAuthStateChanged, signOut, User } from 'firebase/auth';34interface AuthContextType {5 user: User | null;6 loading: boolean;7 logout: () => Promise<void>;8}910const AuthContext = createContext<AuthContextType>({11 user: null,12 loading: true,13 logout: async () => {}14});1516export function AuthProvider({ children }: { children: React.ReactNode }) {17 const [user, setUser] = useState<User | null>(null);18 const [loading, setLoading] = useState(true);1920 useEffect(() => {21 const auth = getAuth();22 const unsubscribe = onAuthStateChanged(auth, (firebaseUser) => {23 setUser(firebaseUser);24 setLoading(false);25 });26 return () => unsubscribe();27 }, []);2829 async function logout() {30 const auth = getAuth();31 await signOut(auth);32 window.location.href = '/login';33 }3435 return (36 <AuthContext.Provider value={{ user, loading, logout }}>37 {children}38 </AuthContext.Provider>39 );40}4142export const useAuth = () => useContext(AuthContext);Expected result: Any component in the app can call logout() from the useAuth() hook to trigger a sign-out with proper cleanup.
Complete working example
1// Complete Firebase sign-out implementation2// Handles auth state, cleanup, and redirect34import { initializeApp } from 'firebase/app';5import {6 getAuth,7 signOut,8 onAuthStateChanged,9 User10} from 'firebase/auth';1112const firebaseConfig = {13 apiKey: 'YOUR_API_KEY',14 authDomain: 'YOUR_PROJECT.firebaseapp.com',15 projectId: 'YOUR_PROJECT_ID',16 storageBucket: 'YOUR_PROJECT.appspot.com',17 messagingSenderId: 'YOUR_SENDER_ID',18 appId: 'YOUR_APP_ID'19};2021const app = initializeApp(firebaseConfig);22const auth = getAuth(app);2324// Sign out and clean up all application state25export async function handleSignOut(): Promise<void> {26 try {27 await signOut(auth);2829 // Clear application-specific cached data30 const appKeys = ['userProfile', 'userSettings', 'cart'];31 appKeys.forEach((key) => localStorage.removeItem(key));32 sessionStorage.clear();3334 // Full page redirect to clear in-memory state35 window.location.href = '/login';36 } catch (error) {37 console.error('Sign out failed:', error);38 // Still redirect even if server-side cleanup fails39 window.location.href = '/login';40 }41}4243// Initialize global auth state listener44export function initAuthListener(45 onSignIn: (user: User) => void,46 onSignOut: () => void47): () => void {48 const unsubscribe = onAuthStateChanged(auth, (user) => {49 if (user) {50 onSignIn(user);51 } else {52 onSignOut();53 }54 });55 return unsubscribe;56}5758// Check current auth state59export function getCurrentUser(): User | null {60 return auth.currentUser;61}Common mistakes when signning Out a User in Firebase
Why it's a problem: Not clearing application state after sign-out, causing the next user to see stale data from the previous session
How to avoid: Clear all user-specific localStorage keys, sessionStorage, and state management stores after calling signOut(). Use a full page redirect with window.location.href for a clean slate.
Why it's a problem: Using React Router navigation instead of window.location.href after sign-out, leaving component state and context values in memory
How to avoid: Use window.location.href = '/login' to force a full page reload that clears all in-memory JavaScript state including React component trees.
Why it's a problem: Not unsubscribing from Firestore/RTDB listeners before sign-out, causing permission-denied errors in the console
How to avoid: Track all active real-time listeners and unsubscribe from them in your sign-out function before calling signOut(auth).
Best practices
- Always redirect with window.location.href after sign-out for a full page reload that clears all JavaScript state
- Set up onAuthStateChanged in your app root to centralize sign-out handling across the application
- Clear localStorage, sessionStorage, and state management stores as part of the sign-out flow
- Unsubscribe from all Firestore and Realtime Database listeners before signing out
- Disable the sign-out button while the async operation is in progress to prevent double clicks
- Provide the sign-out function through React context so components do not need to import Firebase directly
- Handle sign-out errors gracefully and still redirect the user even if the server call fails
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
Show me how to sign out a user in Firebase Auth using the modular v9+ SDK. Include the signOut function, an onAuthStateChanged listener, error handling, clearing local storage, and a React component with loading state.
Implement a complete Firebase Auth sign-out flow in a React TypeScript app using the modular SDK v9+. Include a reusable AuthContext provider with a logout function, onAuthStateChanged listener, localStorage cleanup, and a SignOutButton component.
Frequently asked questions
Does signOut() work when the user is offline?
Yes. signOut() clears the local session regardless of network connectivity. The ID token is invalidated locally, and any server-side revocation happens when the network is available.
Does signOut() sign out from all devices?
No. Firebase Auth signOut() only clears the session on the current device and browser. Other devices where the user is logged in remain signed in until their tokens expire or they sign out manually.
How do I force sign-out on all devices?
Use the Firebase Admin SDK on your server to call auth.revokeRefreshTokens(uid). This invalidates all refresh tokens for the user. On the client side, their session will fail on the next token refresh attempt.
Why do I get permission-denied errors in the console after signing out?
Active Firestore or Realtime Database listeners try to fetch data after the auth state changes to null. Since your security rules require authentication, these listeners receive permission-denied errors. Unsubscribe from all listeners before or during sign-out.
Can I run custom code before the user signs out?
Yes. Call your custom cleanup logic before calling signOut(auth). For example, save unsaved form data, unsubscribe from real-time listeners, or log analytics events before the auth session is cleared.
How do I prevent the sign-out button from being clicked twice?
Use a loading state variable that is set to true when sign-out starts. Disable the button when loading is true to prevent multiple clicks during the async operation.
Can RapidDev help build a complete authentication flow with Firebase?
Yes. RapidDev can implement end-to-end authentication including sign-up, sign-in, sign-out, session management, password reset, and protected routes in your Firebase application.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation