如何在SSR期间使用手动验证的令牌执行Firestore查询?
问题
我希望在服务器端渲染(SSR)期间从Firestore获取数据。我知道可以用REST API(附加令牌到请求头),但不想在服务器端写REST请求,之后又在客户端用标准Firestore查询重复相同逻辑。客户端偏好标准查询(而非REST),因为它支持实时更新,同时我希望在服务器端也能复用客户端的查询(即使没有实时更新的优势)。
我在服务器端已手动验证令牌:
import admin from 'firebase-admin'; import { initializeApp, getApp } from 'firebase/app'; import { getFirestore } from 'firebase/firestore'; const firebaseApp = initializeApp(config); const db = getFirestore(firebaseApp); const decodedIdToken = await admin.auth().verifySessionCookie(sessionCookie); // 令牌验证通过:decodedIdToken.userId = "xxx"
但执行查询时出现错误:
import { collection, getDocs } from 'firebase/firestore'; const querySnapshot = await getDocs(collection(db, 'myCollection'));
错误信息:
{ "code": "permission-denied", "name": "FirebaseError" }
Firestore规则:
service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read, write: if request.auth != null; } } }
客户端可以通过onAuthStateChanged解决该错误,但服务器端无法使用此监听器。请问是否有办法使用手动验证的令牌运行Firestore查询?
解决方案
你可以通过自定义令牌登录的方式,让服务器端的Firestore客户端SDK带上已验证用户的身份信息,步骤如下:
基于已验证的用户ID生成自定义令牌
用Firebase Admin SDK为已验证的decodedIdToken.userId生成自定义令牌:const customToken = await admin.auth().createCustomToken(decodedIdToken.userId);在服务器端的客户端SDK中登录该用户
导入Firebase Auth的客户端方法,使用自定义令牌完成登录:import { getAuth, signInWithCustomToken } from 'firebase/auth'; const auth = getAuth(firebaseApp); await signInWithCustomToken(auth, customToken);执行Firestore查询
登录完成后,再执行你的查询,此时请求会带上有效的request.auth信息,符合Firestore规则的要求:const querySnapshot = await getDocs(collection(db, 'myCollection'));
这种方式既复用了客户端的Firestore查询逻辑,又让服务器端的请求通过了权限验证,不需要单独编写REST请求。
内容的提问来源于stack exchange,提问作者Petr K.
相关产品推荐
相关产品推荐

