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

Firestore规则中用户已登录但request.auth仍为null的问题排查

Firebase Firestore规则中request.auth为null导致权限拒绝问题

问题详情

用户已完成登录,但Firestore安全规则中的request.auth始终返回null,触发权限拒绝错误。未设置安全规则时,认证和数据获取流程完全正常;设置规则后出现以下错误:

FirebaseError: [code=permission-denied]: Missing or insufficient permissions.

将规则改为allow read, write: if true;或allow read, write: if request.auth == null;时,数据请求恢复正常。

相关代码

Firestore安全规则

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null;
    }
  }
}

自定义Auth Hook

import { useEffect, useState } from "react";
import { auth } from "./config";
import { onAuthStateChanged } from "firebase/auth";
import { getUserData } from "../actions/userActions";

function useAuth() {
  const [user, setUser] = useState<any>(undefined);
  const [uid, setUid] = useState<any>(undefined);
  const [firstName, setFirstName] = useState<any>(undefined);
  const [lastName, setLastName] = useState<any>(undefined);
  const [displayName, setDisplayName] = useState<any>(undefined);
  const [email, setEmail] = useState<any>(undefined);
  const [phone, setPhone] = useState<any>(undefined);
  const [address, setAddress] = useState<any>(undefined);
  const [role, setRole] = useState<any>(undefined);

  useEffect(() => {
    const fetchUserData = async (user: any) => {
      let userData = await getUserData(user.uid);
      if (userData) {
        setUid(userData.uid);
        setFirstName(userData.firstName);
        setLastName(userData.lastName);
        setDisplayName(userData.displayName);
        setEmail(userData.email);
        setPhone(userData.phone);
        setAddress(userData.address);
        setRole(userData.role);
      }
    };

    const unsubscribe = onAuthStateChanged(auth, (user) => {
      if (user) {
        setUser(user);
        fetchUserData(user);
      } else {
        setUser(undefined);
        setUid(undefined);
        setFirstName(undefined);
        setLastName(undefined);
        setDisplayName(undefined);
        setEmail(undefined);
        setPhone(undefined);
        setAddress(undefined);
        setRole(undefined);
      }
    });
    return () => unsubscribe();
  });

  return {
    user,
    uid,
    firstName,
    lastName,
    displayName,
    email,
    phone,
    address,
    role,
  };
}

export default useAuth;

getUserData函数

export const getUserData = async (uid: string) => {
  try {
    const snapshot = await getDoc(doc(firestore, "users", uid));
    if (snapshot) return snapshot.data();
    else return undefined;
  } catch (e) {
    console.error("Error at 'getUserData': " + e);
    return undefined;
  }
};

客户端使用方式

const {user} = useAuth()

在组件中渲染:

<p>{user.uid}</p>

已尝试的解决方法

  • 修改规则为request.auth.uid != null
  • 清除浏览器缓存
  • 使用Firebase规则测试平台验证规则
  • 添加条件确保登录完成后再发起数据请求

可能的原因与解决方案

1. Auth与Firestore实例未关联同一Firebase App

确保Firestore和Auth是通过同一个Firebase App实例初始化的,避免因实例不匹配导致认证信息无法同步:

// config.js 示例
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";

const firebaseConfig = { /* 你的项目配置 */ };

const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
export const firestore = getFirestore(app); // 必须使用同一个app实例

2. 认证令牌未完成同步

onAuthStateChanged触发时,用户对象已存在,但Firestore可能还未获取到最新的认证令牌。可以等待令牌就绪后再请求数据:
修改Hook中的fetchUserData函数:

const fetchUserData = async (user: any) => {
  await user.getIdTokenResult(); // 等待令牌刷新完成
  let userData = await getUserData(user.uid);
  // 后续状态更新代码不变
};

3. 规则测试平台使用不当

在Firebase控制台的规则测试工具中,需手动模拟已认证用户:

  • 选择“已认证”选项
  • 输入与实际登录用户一致的uid
  • 测试读取/users/{uid}路径的权限,确认规则是否通过

4. 缓存的旧认证令牌导致异常

尝试登出后重新登录,强制刷新认证令牌:

// 在测试环境中临时调用
auth.signOut().then(() => {
  // 重新登录逻辑
});

也可以清除浏览器的本地存储和缓存,避免旧令牌干扰。

5. 匿名登录或自定义认证的令牌问题

如果使用匿名登录或自定义认证:

  • 匿名登录:确保规则中允许匿名用户(若需要),或切换为常规认证方式测试
  • 自定义认证:检查自定义令牌是否包含有效的uid,且签名正确

内容的提问来源于stack exchange,提问作者Lätizia S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 23:05:03