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

Firebase+NextAuth+FirestoreAdapter如何配置所有者专属读写安全规则?

Firebase + NextAuth + Firestore 安全规则配置问题

问题背景

我基于 Firebase + NextJS,通过 NextAuth 和 FirestoreAdapter 实现认证功能。调试阶段用了全权限开放的安全规则,所有功能都正常运行:

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if true
    }
  }
}

但显然这种规则在生产环境会有极大安全隐患,我需要设置更严格的规则——仅允许文档所有者进行读写操作。尝试过一个解决方案但没能成功:

match /store/{userId}/{document=**} {
        allow read, write: if request.auth.token.id == userId && exists(/databases/$(database)/documents/tokens/$(request.auth.uid)/sessions/$(request.auth.token.sessionToken));
}

核心问题

问题根源在于 NextAuth 与 FirestoreAdapter、Firestore 数据库的交互逻辑:我创建新文档时,文档会被存在users → session.user.id → drafts → 文档路径下,但 Firebase 的用户 UID 和session.user.id并不一致,这直接导致之前的安全规则失效。

现在需要找到正确的安全规则配置方式,让只有session.user.id与文档的userId字段匹配的用户,才能对数据库进行读写操作。

Firestore文档路径结构截图

相关代码

创建新草稿的代码

const createNewDraft = async () => {
      const doc = await addDoc(
        collection(db, "users", session?.user?.id!, "drafts"),
        {
          userId: session?.user?.id!,
          createdAt: serverTimestamp(),
        }
      );
 };

[...nextAuth].ts 代码

import { FirestoreAdapter } from "@next-auth/firebase-adapter";
import { GoogleAuthProvider, signInWithCredential } from "firebase/auth";
import { cert } from "firebase-admin/app";
import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import "firebase/firestore";

import { fbAuth } from "../../../../firebase";

const sa = JSON.parse(process.env.NEXT_PUBLIC_FIREBASE_SERVICE_KEY);

export const authOptions = {
  providers: [
    GoogleProvider({
      clientId: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID!,
      clientSecret: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_SECRET!,
    }),
  ],
  callbacks: {
    async signIn({ user, account, profile, email, credentials }) {
      try {
        const googleCredential = GoogleAuthProvider.credential(
          account?.id_token
        );
        const userCredential = await signInWithCredential(
          fbAuth,
          googleCredential
        ).catch((e) => {
          console.log(e);
          return false;
        });
        return !!userCredential;
      } catch (e) {
        console.log(e);
        return false;
      }
    },
    session: async ({ session, token }) => {
      if (session?.user) {
        session.user.id = token.sub;
      }
      return session;
    },
  },
  session: {
    strategy: "jwt",
  },
  adapter: FirestoreAdapter({
    credential: cert({
      projectId: sa.project_id,
      clientEmail: sa.client_email,
      privateKey: sa.private_key,
    }),
  }),
};
export default NextAuth(authOptions);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 00:52:40