如何实现两个Firebase项目的用户列表同步?
实现两个Firebase项目的用户跨项目登录/同步
方案1:使用自定义令牌实现跨项目登录(实时共享登录状态)
这种方式无需完全同步用户列表,用户在源项目登录后,可生成自定义令牌直接登录目标项目。
在源Firebase项目(已有用户的项目)中部署Cloud Function生成自定义令牌:
- 安装Firebase CLI并初始化Cloud Functions
- 编写函数,用目标项目的服务账号私钥生成令牌:
const functions = require("firebase-functions"); const admin = require("firebase-admin"); const targetAdmin = require("firebase-admin"); // 初始化源项目Admin SDK admin.initializeApp(); // 初始化目标项目Admin SDK(需导入目标项目的服务账号JSON) const targetServiceAccount = require("./target-project-service-account.json"); targetAdmin.initializeApp({ credential: targetAdmin.credential.cert(targetServiceAccount), }, "target"); exports.generateCrossProjectToken = functions.https.onCall(async (data, context) => { if (!context.auth) { throw new functions.https.HttpsError("unauthenticated", "用户未登录"); } const user = await admin.auth().getUser(context.auth.uid); // 生成目标项目的自定义令牌,保留核心用户信息 const customToken = await targetAdmin.auth().createCustomToken(user.uid, { email: user.email, displayName: user.displayName }); return { customToken }; });- 部署该函数到源项目
客户端实现跨项目登录:
// 先登录源项目 const sourceAuth = firebase.initializeApp(sourceConfig, "source").auth(); await sourceAuth.signInWithEmailAndPassword(email, password); // 调用Cloud Function获取目标项目令牌 const generateToken = firebase.functions().httpsCallable("generateCrossProjectToken"); const result = await generateToken(); // 登录目标项目 const targetAuth = firebase.initializeApp(targetConfig, "target").auth(); await targetAuth.signInWithCustomToken(result.data.customToken);
方案2:一次性用户列表迁移(同步现有全部用户)
如果需要将源项目的现有用户批量同步到目标项目,可使用Firebase Auth的导出导入工具:
导出源项目用户:
- 用Firebase CLI登录并切换到源项目
- 执行命令导出用户到JSON文件:
firebase auth:export users.json --format=json导入到目标项目:
- 切换到目标项目
- 执行导入命令(需匹配源项目的密码哈希参数,可在源项目控制台「身份验证」->「设置」中查看):
firebase auth:import users.json --hash-algo=SCRYPT --rounds=8 --mem-cost=14
方案3:实时同步用户变更(新增/修改自动同步)
如果需要源项目的用户新增、信息修改等操作实时同步到目标项目,可通过Cloud Functions监听用户事件:
- 编写同步函数:
const functions = require("firebase-functions"); const admin = require("firebase-admin"); const targetAdmin = require("firebase-admin"); admin.initializeApp(); const targetServiceAccount = require("./target-project-service-account.json"); targetAdmin.initializeApp({ credential: targetAdmin.credential.cert(targetServiceAccount), }, "target"); // 监听用户创建事件,同步到目标项目 exports.syncUserCreate = functions.auth.user().onCreate(async (user) => { try { await targetAdmin.auth().createUser({ uid: user.uid, email: user.email, emailVerified: user.emailVerified, displayName: user.displayName, photoURL: user.photoURL, disabled: user.disabled }); } catch (error) { functions.logger.error("同步用户创建失败:", error); } }); // 监听用户更新事件,同步到目标项目 exports.syncUserUpdate = functions.auth.user().onUpdate(async (change) => { const updatedUser = change.after; try { await targetAdmin.auth().updateUser(updatedUser.uid, { email: updatedUser.email, emailVerified: updatedUser.emailVerified, displayName: updatedUser.displayName, photoURL: updatedUser.photoURL, disabled: updatedUser.disabled }); } catch (error) { functions.logger.error("同步用户更新失败:", error); } });注意:源项目用户的密码为哈希存储,无法直接获取明文,同步后目标项目的用户需通过自定义令牌登录,或触发密码重置流程。
内容的提问来源于stack exchange,提问作者Josef Pa
相关产品推荐
相关产品推荐

