如何在Firebase Admin中验证输入密码与用户密码是否匹配
密码验证实现方案
现有代码的问题
- 异步逻辑处理错误:
admin.auth().getUserByEmail是异步操作,你的函数直接同步返回true,验证逻辑根本没执行就返回结果了。 - 密码对比逻辑错误:
userRecord.password(实际应为passwordHash)是Firebase用SCRYPT算法生成的哈希值,你直接和明文密码对比肯定不匹配;而且bcrypt和SCRYPT是完全不同的哈希算法,无法用bcrypt验证Firebase的哈希密码。
正确实现方式
Firebase Auth使用自定义SCRYPT算法处理密码哈希,必须用Firebase的SCRYPT参数验证输入密码:
获取必要参数
通过getUserByEmail拿到用户的passwordHash(哈希密码)和passwordSalt(盐值),同时从Firebase控制台获取项目的SCRYPT配置:signerKey、rounds、memCost。执行SCRYPT哈希验证
用这些参数对输入密码进行哈希计算,再和存储的passwordHash对比。
示例代码
const crypto = require('crypto'); const admin = require('firebase-admin'); // 从Firebase控制台获取的SCRYPT参数 const SCRYPT_CONFIG = { signerKey: '你的项目signerKey', rounds: 8, memCost: 14 }; async function verifyPassword(email, inputPassword) { try { const userRecord = await admin.auth().getUserByEmail(email); // 无哈希密码或盐值时直接返回验证失败 if (!userRecord.passwordHash || !userRecord.passwordSalt) { return false; } // 解码Base64格式的哈希和盐 const storedHash = Buffer.from(userRecord.passwordHash, 'base64'); const salt = Buffer.from(userRecord.passwordSalt, 'base64'); // 生成输入密码的SCRYPT派生密钥 const derivedKey = crypto.scryptSync(inputPassword, salt, 32, { N: 1 << SCRYPT_CONFIG.memCost, r: SCRYPT_CONFIG.rounds, p: 1 }); // 合并signerKey与派生密钥,计算SHA-256哈希 const combinedBuffer = Buffer.concat([Buffer.from(SCRYPT_CONFIG.signerKey, 'base64'), derivedKey]); const computedHash = crypto.createHash('sha256').update(combinedBuffer).digest(); // 安全对比哈希值(防止时序攻击) return crypto.timingSafeEqual(computedHash, storedHash); } catch (err) { console.error('密码验证出错:', err); return false; } }
官方文档翻译
- 用户的哈希密码(Base64编码),仅当使用Firebase Auth哈希算法(SCRYPT)时才会返回。如果上传用户时使用了其他哈希算法(这在从其他认证系统迁移时很常见),该字段将为空字符串。如果未设置密码,该字段为null。仅当从[原文未补充完整的来源]获取用户时才会提供该字段。
内容的提问来源于stack exchange,提问作者Gbenga B Ayannuga
相关产品推荐
相关产品推荐

