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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 10:20:43