You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修复NextAuth+Firebase获取用户数据时的权限不足错误

问题描述

我正在使用NextAuth和Firebase获取用户数据,但调用getBalance函数时出现错误:

Uncaught (in promise) FirebaseError: Missing or insufficient permissions

以下是相关代码及配置:

函数代码

async function getBalance(uid) {
  const userRef = doc(db, "users", uid);
  const userDoc = await getDoc(userRef);

  if (userDoc.exists()) {
    const { tokens } = userDoc.data();
    return tokens;
  } else {
    return null;
  }
}

Firebase Admin配置

import { getApps } from "firebase-admin/app";
import admin from "firebase-admin";

const serviceAccount = JSON.parse(process.env.FIREBASE_SERVICE_ACCOUNT_KEY);

if (!getApps().length) {
  admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
  });
}

const adminDb = admin.firestore();
const adminAuth = admin.auth();

export { adminDb, adminAuth };

Firebase客户端配置

import { getFirestore } from "firebase/firestore";
import { getApps, initializeApp } from "firebase/app";

const firebaseConfig = {
  apiKey: process.env.FIREBASE_APIKEY,
  authDomain: process.env.FIREBASE_AUTHDOMAIN,
  databaseURL: process.env.FIREBASE_DATABASEURL,
  projectId: process.env.FIREBASE_PROJECTID,
  storageBucket: process.env.FIREBASE_STORAGEBUCKET,
  messagingSenderId: process.env.FIREBASE_MESSAGINGSENDERID,
  appId: process.env.FIREBASE_APPID,
  measurementId: process.env.FIREBASE_MEASUREMENTID,
};

const app = getApps().length ? getApp() : initializeApp(firebaseConfig);
const db = getFirestore(app);

export { db };

数据库结构

/users/email@example.com/chats/UN3XookDLjiJvqsW7GPG/messages/2gKLNAKDGiNWy2TvcFWq
(其中email@example.com为用户uid)

当前Firestore规则

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read, write: if request.auth.uid == userId;
      
      match /{document=**} {
        allow read, write: if request.auth.uid == userId;
      }
    }
  }
}

测试规则(可正常运行)

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.time < timestamp.date(2023, 4, 19);
    }
  }
}

请问需如何修改Firebase规则以允许访问用户数据?


解决方案

问题核心是规则校验逻辑与实际用户ID的存储方式不匹配,结合你的场景可按以下方式修复:

1. 调整Firestore规则适配邮箱格式的用户ID

你的数据库中用户文档ID是邮箱地址,但默认request.auth.uid是Firebase Auth生成的唯一标识符(非邮箱),因此需要修改规则的校验条件:

修改后的规则

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // 匹配/users下的所有层级(包括子集合chats、messages)
    match /users/{userId}/{document=**} {
      allow read, write: if request.auth != null && request.auth.token.email == userId;
    }
  }
}

规则说明

  • 直接覆盖/users/{userId}下的所有文档和子集合,避免嵌套匹配的冗余
  • 用request.auth.token.email替代request.auth.uid,与你存储的邮箱格式用户ID匹配
  • 增加request.auth != null校验,确保用户已完成认证

2. 确保客户端请求携带有效认证信息

调用getBalance时需确认:

  • 用户已通过NextAuth完成登录,且当前会话有效
  • 传入的uid参数与Firebase Auth返回的用户邮箱完全一致(大小写、拼写无误差)

3. 备选优化:改用Firebase Auth的uid作为用户文档ID

如果是误将邮箱设为用户文档ID,建议改为使用Firebase Auth生成的uid作为文档ID:

  • 用户创建时,用adminAuth.createUser返回的uid作为/users下的文档ID
  • 保持你原有的Firestore规则即可生效,此时request.auth.uid与userId完全匹配

内容的提问来源于stack exchange,提问作者Tui

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 17:08:18