Firebase
Broken Authentication

Broken Authentication in Firebase Apps

Firebase Authentication reliably handles user sign-in, but authentication is only half the security equation. Authorization, deciding what each user can access, must be enforced through Security Rules and Cloud Functions. When it is not, any authenticated user can access any other user's data.

Scan Your Firebase App

How It Happens

Firebase Auth correctly identifies users, but developers implement authorization poorly. The most common mistake is writing Firestore rules like allow read, write: if request.auth != null, which grants every logged-in user access to every document. This checks authentication (are you logged in?) but not authorization (are you allowed to access this specific data?). Client-side authorization is another frequent pattern. Developers hide admin features behind UI checks (if user.customClaims.admin) but the underlying Firestore queries are unprotected. An attacker using the Firebase SDK directly can query any collection that only checks for authentication. Custom claims are powerful but often misused. Developers set custom claims from client-side code (which is not possible) or store roles in user-editable Firestore documents. If a user can modify their own role document, they can escalate to admin privileges.

Impact

Broken authorization allows any authenticated user to read, modify, or delete any other user's data. In a Firebase app with user profiles, messages, and files, this means complete cross-user data exposure. Privilege escalation through editable role documents is particularly dangerous. An attacker who can set their own role to "admin" gains access to admin Cloud Functions, admin-only collections, and management features. For Firebase apps with Cloud Functions that trust client-provided role information, broken auth extends beyond Firestore to any backend operation the Cloud Function performs, including sending emails, processing payments, or accessing third-party services.

How to Detect

Create two Firebase user accounts. Log in as User A and note the data visible to them. Then use the Firebase SDK with User B's credentials to attempt accessing User A's data. If the query succeeds, authorization is broken. Review Firestore rules for conditions that only check request.auth != null without verifying ownership (request.auth.uid == resource.data.userId). Look at Cloud Functions for missing permission checks. Vibe App Scanner detects Firebase apps and tests authorization boundaries by analyzing Security Rules configuration and testing data isolation between authentication contexts.

How to Fix

Rewrite Firestore rules to check document ownership, not just authentication. Replace request.auth != null with request.auth.uid == resource.data.userId for user-owned documents. For subcollection patterns, use path-based checks: match /users/{userId}/data/{docId} with request.auth.uid == userId. Implement role-based access using Firebase custom claims, which are set server-side through the Admin SDK and cannot be modified by clients. Set claims in a Cloud Function triggered by an admin action, not from client code. Add authorization checks to every Cloud Function. Use context.auth.uid and context.auth.token.admin (custom claims) to verify the caller has permission for the requested operation. Never trust role information sent in the request body. Use Firebase App Check to prevent unauthorized access from outside your application, and combine it with Security Rules for defense-in-depth.

Code Examples

Firestore Security Rules authorization

Vulnerable
// Only checks authentication, not authorization
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /orders/{orderId} {
      allow read, write: if request.auth != null;
      // Any logged-in user can see ALL orders
    }
  }
}
Secure
// Checks document ownership
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /orders/{orderId} {
      allow read, update, delete:
        if request.auth.uid == resource.data.userId;
      allow create:
        if request.auth.uid == request.resource.data.userId;
    }
    // Admin-only collection using custom claims
    match /admin/{docId} {
      allow read, write:
        if request.auth.token.admin == true;
    }
  }
}

Frequently Asked Questions

Is Firebase Authentication itself insecure?

No. Firebase Auth handles sign-in, token management, and session security correctly. The issue is authorization: deciding what each authenticated user can access. This is the developer's responsibility through Security Rules and Cloud Function logic.

How do I set up admin users in Firebase?

Use Firebase custom claims set through the Admin SDK in a Cloud Function. Call admin.auth().setCustomUserClaims(uid, { admin: true }) from a server-side function. Then check request.auth.token.admin == true in Security Rules. Never store admin status in a user-editable document.

Can Firebase App Check prevent broken authorization?

App Check verifies that requests come from your legitimate app, which stops unauthorized SDK usage. However, it does not prevent a legitimate user of your app from accessing other users' data. Security Rules are still needed for authorization.

Is Your App Vulnerable?

VAS automatically scans for broken authentication and other security issues in Firebase apps. Get actionable results with step-by-step fixes.

Scans from $5, results in minutes.