Cloudflare Worker中Firestore Lite的Firebase安全规则不生效问题
解决Cloudflare Worker中Firestore Lite安全规则request.auth为null的问题
问题核心在于Cloudflare Worker是无状态环境,Firebase Auth的默认持久化机制(如localStorage)无法生效,导致Firestore Lite无法自动将用户认证信息附加到请求中,因此安全规则里的request.auth始终为null。
解决方法:手动为Firestore请求附加ID Token
Firestore后端需要通过请求头里的Authorization: Bearer <id_token>来验证用户身份,进而填充安全规则中的request.auth。你需要在初始化Firestore时,配置自定义的fetch函数,将有效的ID Token注入到每个请求的头中。
步骤1:确保获取到原始ID Token
你的认证流程中,除了解码后的DecodedIdToken,还需要保留用户的原始ID Token(一般在认证中间件中可以直接获取,比如Hono的Firebase Auth中间件会返回idToken字段)。
步骤2:修改Firebase类,配置带认证的Fetch函数
更新你的Firebase类,在初始化Firestore时传入自定义fetch,自动附加ID Token:
import { initializeApp } from 'firebase/app'; import { getAuth, initializeAuth } from 'firebase/auth'; import { initializeFirestore, Firestore } from 'firebase/firestore/lite'; import { DecodedIdToken } from '@fiboup/hono-firebase-auth'; export class Firebase { private app; public auth; private idToken?: string; public jwtPayload?: DecodedIdToken; private _db?: Firestore; constructor(apiKey: string, authDomain: string, databaseURL: string, projectId: string, appId: string, idToken?: string, userPayload?: DecodedIdToken) { this.app = initializeApp({ apiKey, authDomain, databaseURL, projectId, appId }); this.auth = initializeAuth(this.app); this.idToken = idToken; this.jwtPayload = userPayload; } public get db(): Firestore { if (!this._db) { // 自定义fetch函数,自动添加Authorization头 const authFetch = async (url: string, options: RequestInit = {}) => { const headers = new Headers(options.headers); if (this.idToken) { headers.set('Authorization', `Bearer ${this.idToken}`); } return fetch(url, { ...options, headers }); }; this._db = initializeFirestore(this.app, { fetch: authFetch }); } return this._db; } // 保留原有的userPayload getter... public get userPayload(): FirebaseJwtPayload | undefined { return { ...this.jwtPayload, ...{ picture: () => { try { return new URL(this.jwtPayload?.picture); } catch (error) { console.error('Failed to get firebase user picture', error); return undefined; } }, auth_time: new Date(this.jwtPayload?.auth_time * 1000), iat: new Date(this.jwtPayload?.iat * 1000), exp: new Date(this.jwtPayload?.exp * 1000), }, }; } }
步骤3:在实例化Firebase时传入ID Token
当你创建Firebase实例时,将认证流程中获取到的原始ID Token传入:
// 假设从Hono中间件中获取到idToken和decodedToken const firebase = new Firebase( API_KEY, AUTH_DOMAIN, DATABASE_URL, PROJECT_ID, APP_ID, idToken, // 传入原始ID Token decodedToken );
关键说明
- 必须使用原始ID Token,而不是解码后的payload:Firebase后端需要验证token的签名和有效性,解码后的信息无法用于身份验证。
- 确保ID Token未过期:可以在使用前检查
exp时间,或在认证中间件中自动刷新过期的token。 - Cloudflare Worker的fetch是原生支持的,无需额外配置跨域或其他特殊处理。
这样配置后,Firestore的所有请求都会携带用户的认证信息,安全规则中的request.auth就会被正确填充,你的规则allow read, write: if request.auth != null;就能正常生效。
内容的提问来源于stack exchange,提问作者ChainFuse
相关产品推荐
相关产品推荐

