This error occurs when your app lacks the necessary permissions to read or write files in Firebase Cloud Storage. Learn how to authenticate users, configure security rules, and fix access issues in your Firebase project.
The "storage/permission-denied" error is Firebase Cloud Storage's way of protecting your data when access is not allowed. This happens when a user tries to perform an operation (read or write) on a storage file but the current Firebase Security Rules do not permit the action. The error is typically caused by one of three scenarios: the user is not authenticated, the security rules do not match the user's identity, or the rules explicitly block the requested operation. Firebase Cloud Storage always enforces these rules on the client side to prevent unauthorized access to your files.
The most common cause is that the user is not signed in. Check if the user is authenticated before attempting to read or write:
import { getAuth, signInAnonymously } from 'firebase/auth';
import { getStorage, ref, uploadBytes } from 'firebase/storage';
const auth = getAuth();
const storage = getStorage();
// First, sign in the user (or use an existing session)
if (!auth.currentUser) {
await signInAnonymously(auth);
}
// Now upload is allowed by the rules
const storageRef = ref(storage, 'files/myfile.txt');
await uploadBytes(storageRef, file);Go to the Firebase Console > Storage > Rules and check the current rules. The default rules require authentication:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}These rules mean: "Allow read and write ONLY if user is authenticated (request.auth is not null)". If your user is not signed in, the rules block the request.
For development or public files, you can temporarily allow unauthenticated access. Warning: Only use this for testing or public files. This is insecure in production:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if true;
}
}
}Always secure this again before launching to production.
Use user IDs in your storage paths to restrict access. This allows only the owner to access their files:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
// Allow users to read/write only their own files
match /users/{userId}/{allPaths=**} {
allow read, write: if request.auth.uid == userId;
}
}
}In your code, structure your upload paths with the user ID:
const userId = auth.currentUser.uid;
const storageRef = ref(storage, `users/${userId}/myfile.txt`);
await uploadBytes(storageRef, file);Add error handling to gracefully handle permission denied errors:
import { getStorage, ref, uploadBytes } from 'firebase/storage';
try {
const storageRef = ref(storage, 'files/myfile.txt');
await uploadBytes(storageRef, file);
console.log('Upload successful');
} catch (error) {
if (error.code === 'storage/unauthorized' || error.code === 'storage/permission-denied') {
console.error('Permission denied. Make sure you are signed in.');
// Redirect user to login or show error message
} else {
console.error('Upload failed:', error.message);
}
}Use the Firebase Emulator to test your rules locally without affecting production:
firebase emulators:startThis lets you debug security rules and authentication flows before deploying to production. You can also check rule evaluation in the Firebase Console under Storage > Rules > Simulate.
If using the Firebase Admin SDK on a backend server, security rules are bypassed completely—all operations are allowed. Permission denied errors only apply to web and mobile clients. For fine-grained access control, consider implementing custom claims in Firebase Auth tokens and checking them in your rules. If you are using different storage buckets, verify you are accessing the correct bucket. Some users experience permission denied even with correct rules due to cached tokens—try signing out and signing back in. You can also use custom authentication tokens (from your backend) to grant specific permissions to users.
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