React Native Firebase v6中Firebase安全规则request.auth为null问题排查
问题描述
在Expo托管的React Native应用中,使用@react-native-firebase和@react-native-google-signin实现谷歌登录,用户完成认证后auth().currentUser可正确返回用户对象,但Firestore规则设置为request.auth != null时会拒绝文档获取请求,设置为request.auth == null时反而允许访问。
当前Firestore规则
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read, write: if request.auth != null; } } }
React Native相关代码
谷歌登录函数
const signInWithGoogle = async () => { try { setLoading(true); await GoogleSignin.hasPlayServices({ showPlayServicesUpdateDialog: true, }); const { idToken } = await GoogleSignin.signIn(); const googleCredential = auth.GoogleAuthProvider.credential(idToken); auth() .signInWithCredential(googleCredential) .then(async (data) => { await setUserInFirestore(data.user); const { uid, displayName, email, photoURL } = data.user; await AsyncStorage.setItem( "user", JSON.stringify({ uid, displayName, email, photoURL }) ); if (data.user?.metadata) { const date = data.user.metadata.creationTime.slice(0, 10); await AsyncStorage.setItem("userDate", date); } }) .catch((error) => { setError(error); navigation.navigate(routes.WELCOME); }); } catch (error) { setError(error); navigation.navigate(routes.WELCOME); } };
setUserInFirestore方法
const setUserInFirestore = async (user) => { const { uid, displayName, email, photoURL } = user; try { const userRef = doc(db, "users", uid); const snapshot = await getDoc(userRef); if (!snapshot.exists()) { await setDoc(userRef, { displayName, email, photoURL, uid, subscription: null, createdAt: new Date(), }); setIsNewUser(true); } setUser(user); setUserContext(user); } catch (error) { setError(error); } };
初始化代码
useEffect(() => { GoogleSignin.configure({ webClientId: key, }); const unsubscribe = auth().onAuthStateChanged((user) => { setUser(user); setLoading(false); }); return unsubscribe; }, []);
已尝试的解决方案
- 全局更新firebase-tools,无效果
使用的依赖版本
- "firebase": "^9.21.0"
- "@react-native-firebase/app": "^17.4.3"
- "@react-native-firebase/auth": "^17.4.3"
解决方案
统一Firestore实例来源
确保Firestore实例使用@react-native-firebase/firestore初始化,而非web版firebase/firestore。RN环境下@react-native-firebase的实例会自动同步Auth会话,web版无法关联RN的Auth状态:// 正确导入方式 import firestore from '@react-native-firebase/firestore'; const db = firestore();移除项目中web版
firebase依赖,避免版本冲突。强制刷新Auth令牌
在用户登录成功后,强制刷新ID令牌,确保Firestore请求使用最新的有效令牌:
在signInWithCredential的then回调中添加:await data.user.getIdToken(true); // 强制刷新令牌调试Firestore规则中的auth状态
在规则中添加调试语句,查看request.auth的实际值:rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read, write: if request.auth != null || debug(request.auth); } } }通过Firebase控制台的规则模拟器测试,或查看规则执行日志,确认
request.auth是否为null。检查Firebase项目配置
- 确认Firebase项目中已添加Expo应用的Android SHA-1指纹(可通过
expo fetch:android:hashes获取)。 - 验证app.json中Firebase的Android/iOS客户端ID配置正确。
- 确认Firebase项目中已添加Expo应用的Android SHA-1指纹(可通过
版本兼容性调整
@react-native-firebase v17对应Firebase SDK v9,但web版firebase包可能和RN版存在兼容性问题,建议完全使用@react-native-firebase系列包,移除firebase依赖。
内容的提问来源于stack exchange,提问作者pacehut

