The "PERMISSION_DENIED: User is not authenticated" error occurs when you attempt to access Firestore or Realtime Database without signing in a user first. Firebase security rules require authentication by default, and unauthenticated requests are blocked to protect your data.
The "PERMISSION_DENIED: User is not authenticated" error means your code is trying to read or write data in Firebase (Firestore or Realtime Database) while no user is logged in. Firebase security rules check the `request.auth` context to determine if an operation is allowed. When `request.auth` is null (indicating no authenticated user), the default security rules deny the operation to prevent unauthorized access. This is a security feature protecting your database from malicious or unintended access.
The most direct fix is to ensure a user is authenticated before any database operations:
Web/JavaScript:
import { initializeApp } from "firebase/app";
import { getAuth, signInAnonymously, onAuthStateChanged } from "firebase/auth";
import { getFirestore, collection, getDocs } from "firebase/firestore";
const firebaseApp = initializeApp({
apiKey: "YOUR_API_KEY",
projectId: "YOUR_PROJECT_ID",
// ... other config
});
const auth = getAuth(firebaseApp);
const db = getFirestore(firebaseApp);
// Sign in anonymously first
signInAnonymously(auth)
.then(() => {
// Now safe to access Firestore
return getDocs(collection(db, "users"));
})
.then(snapshot => {
console.log("Data retrieved:", snapshot.docs.map(doc => doc.data()));
})
.catch(error => console.error("Error:", error));React Pattern:
import { useEffect, useState } from "react";
import { getAuth, signInAnonymously } from "firebase/auth";
import { getFirestore, collection, getDocs } from "firebase/firestore";
export function MyComponent() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const auth = getAuth();
const db = getFirestore();
// Sign in and load data
signInAnonymously(auth)
.then(() => getDocs(collection(db, "users")))
.then(snapshot => {
setData(snapshot.docs.map(doc => doc.data()));
setLoading(false);
})
.catch(error => {
console.error("Error:", error);
setLoading(false);
});
}, []);
if (loading) return <div>Loading...</div>;
return <div>{JSON.stringify(data)}</div>;
}Instead of immediately querying the database, wait for the authentication state to initialize:
import { getAuth, onAuthStateChanged } from "firebase/auth";
import { getFirestore, collection, getDocs } from "firebase/firestore";
const auth = getAuth();
const db = getFirestore();
// Wait for auth state to initialize
onAuthStateChanged(auth, (user) => {
if (user) {
// User is signed in, now safe to query database
getDocs(collection(db, "users"))
.then(snapshot => {
console.log("Data:", snapshot.docs.map(doc => doc.data()));
})
.catch(error => console.error("Query error:", error));
} else {
// User is not signed in
console.log("User not authenticated. Sign in first.");
}
});This pattern is essential because onAuthStateChanged is asynchronous and triggers when Firebase connects to the backend. Queries before this completes will fail with permission denied.
Check your Firestore/Realtime Database security rules:
1. Go to [Firebase Console](https://console.firebase.google.com)
2. Navigate to Firestore Database → Rules (or Realtime Database → Rules)
3. Review the current rules
For development testing only (insecure):
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true; // ONLY for testing!
}
}
}For authenticated users (recommended):
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}For user-specific data:
match /users/{userId} {
allow create: if request.auth != null;
allow read, update, delete: if request.auth != null && request.auth.uid == userId;
}If your app allows unauthenticated users, enable anonymous sign-in:
1. Go to [Firebase Console](https://console.firebase.google.com)
2. Navigate to Authentication → Sign-in method
3. Enable Anonymous provider
4. Update your security rules to allow anonymous access:
match /public/{document=**} {
allow read: if request.auth != null; // Any authenticated user (including anonymous)
}Then sign in anonymously before queries:
import { signInAnonymously } from "firebase/auth";
const auth = getAuth();
await signInAnonymously(auth);
// Now database queries will workEnsure Firebase is properly initialized before any database access:
import { initializeApp } from "firebase/app";
import { getAuth, signInAnonymously } from "firebase/auth";
import { getFirestore, collection, getDocs } from "firebase/firestore";
// Step 1: Initialize Firebase
const app = initializeApp({
apiKey: "YOUR_API_KEY",
projectId: "YOUR_PROJECT_ID",
// ... other config from Firebase Console
});
// Step 2: Get references
const auth = getAuth(app); // Pass app instance explicitly
const db = getFirestore(app);
// Step 3: Sign in
await signInAnonymously(auth);
// Step 4: Now access database
const snapshot = await getDocs(collection(db, "users"));
console.log("Success:", snapshot.docs);Common mistake: calling getAuth() or getFirestore() before initializeApp() completes.
If using Firebase with Next.js or SSR frameworks, authentication state is not available on the server, so all Firestore queries must happen client-side within a browser context. Use "use client" in React Server Components to move code to the browser. For server-side database access, use the Firebase Admin SDK which bypasses security rules entirely. If using the Firebase Emulator Suite locally, ensure your connectFirestoreEmulator() is called before any queries and that the emulator is running on the expected port (default 8080). The error can also occur briefly during app initialization before onAuthStateChanged fires—this is expected and resolves once initialization completes.
Callable Functions: INTERNAL - Unhandled exception
How to fix "Callable Functions: INTERNAL - Unhandled exception" in Firebase
auth/invalid-hash-algorithm: Hash algorithm doesn't match supported options
How to fix "auth/invalid-hash-algorithm: Hash algorithm doesn't match supported options" in Firebase
Hosting: CORS configuration not set up properly
How to fix CORS configuration in Firebase Hosting
auth/reserved-claims: Custom claims use reserved OIDC claim names
How to fix "reserved claims" error when setting custom claims in Firebase
Callable Functions: UNAUTHENTICATED - Invalid credentials
How to fix "UNAUTHENTICATED - Invalid credentials" in Firebase Callable Functions