Firebase规则用于修复使用NextAuth访问用户数据时的“缺少权限或权限不足”错误

r8uurelv  于 2023-04-11  发布在  其他
关注(0)|答案(2)|浏览(140)

我正在使用NextAuth和Firebase检索用户的数据,但当我尝试运行此函数时遇到以下错误:
Uncaught(in promise)FirebaseError:缺少权限或权限不足。

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中设置规则来修复此错误?以下是我的配置文件:

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 };
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.comuid
以下是我目前的Firebase规则:

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规则中的哪些内容才能允许访问用户数据?

zvms9eto

zvms9eto1#

Firestore安全规则中的request.auth由Firebase自动填充,但仅当用户使用Firebase身份验证登录时。
由于您未登录Firebase身份验证,因此不会填充request.auth,并且您的规则检查将拒绝所有访问。
要解决这个问题,您需要获取登录到Next Auth的用户的信息,并使用该信息登录到Firebase。此流程在custom sign-inminting custom tokens的文档中进行了描述,因此我建议遵循这些来解决问题。

6vl6ewon

6vl6ewon2#

这是对我有用的代码(基于Frank货车Puffelen建议的文档)。
在处理用户登录的位置放置以下内容:

import { auth, db } from "../firebase/firebase";
import { signInWithCustomToken } from "firebase/auth";
import { useSession } from "next-auth/react";

  const { data: session } = useSession();

  const signInWithFirebase = async (session) => {
    const response = await fetch("/api/createCustomToken", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ user: session.user }),
    });

    const customToken = await response.json();

    signInWithCustomToken(auth, customToken.token)
      .then((userCredential) => {
        const user = userCredential.user;
      })
      .catch((error) => {
        const errorCode = error.code;
        const errorMessage = error.message;
        // ...
      });
  };

  useEffect(() => {
    if (session) {
      signInWithFirebase(session);
    }
  }, [session]);

firebaseAdmin.js

import admin from "firebase-admin";

const serviceAccount = JSON.parse(process.env.FIREBASE_SERVICE_ACCOUNT_KEY);
if (!admin.apps.length) {
  admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
  });
}

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

export { adminDb, adminAuth };

firebase.js

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

const firebaseConfig = {
apiKey: process.env.FIREBASE_APIKEY,
authDomain: process.env.FIREBASE_AUTHDOMAIN,
databaseURL: process.env.FIREBASE_DATABASEURL,
projectId: process.env.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);
const auth = getAuth(app);
export { db, auth };

pages/api/createCustomToken.js

import { adminAuth } from "@/firebase/firebaseAdmin";

export default async function handler(req, res) {
  if (req.method !== "POST") {
    res.status(405).json({ message: "Method not allowed" });
    return;
  }

  const { user } = req.body;

  const uid = user.email;

  try {
    const customToken = await adminAuth.createCustomToken(uid);

    res.status(200).json({ token: customToken });
  } catch (error) {
    console.error("Error creating custom token:", error);
    res.status(500).json({ message: "Error creating custom token" });
  }
}

请注意,这段代码对我来说是有效的,您可能需要进行更改以使其适应您自己的特定用例。

相关问题