首页 / 资讯中心 / 文章详情

Firebase JS SDK 的 TotpMultiFactorAssertion:TOTP 第二因子认证断言的注册与登录实战解析

Firebase JS SDK 的 TotpMultiFactorAssertion:TOTP 第二因子认证断言的注册与登录实战解析 ★ FEATURED ARTICLE
开发工具后端【免费下载链接】firebase-js-sdkFirebase Javascript SDK项目地址https://gitcode.com/gh_mirrors/fi/firebase-js-sdk点击查看免费下载本文以 Firebase JavaScript SDK 官方 API 参考文档 auth.totpmultifactorassertion.md 为骨架深入讲解TotpMultiFactorAssertion接口在 TOTP基于时间的一次性密码多因子认证体系中的定位、产生方式与底层实现。读完本文你将掌握如何用TotpMultiFactorGenerator构造 TOTP 断言完成第二因子的注册与二次登录、断言的内部状态机如何驱动注册/登录两个 API 流程以及 SDK 中对应的源码与测试证据位置。一、TotpMultiFactorAssertion 是什么按照官方参考文档的定义TotpMultiFactorAssertion是The class for asserting ownership of a TOTP second factor.即用于证明用户拥有某个 TOTP 第二因子的断言对象。它本身不包含任何业务字段而是通过继承关系接入 Firebase Auth 的多因子断言体系export interface TotpMultiFactorAssertion extends MultiFactorAssertion {}其基类 MultiFactorAssertion 定义在 packages/auth/src/model/public_types.ts#L611只有一个只读属性factorId用于标识第二因子的类型。TOTP 断言在构造时即被固定为FactorId.TOTP即字符串字面量totp。在 Firebase Auth 的 MFA 模型里一个断言assertion是用户在完成第二因子验证输入验证码、提供 TOTP 一次性密码等后产生的一个凭证载体它不直接携带敏感信息而是由 SDK 内部把断言携带的 OTP 与注册/登录上下文session组合成对后端的请求。这一点可以从 mfa_assertion.ts 的抽象基类看到所有断言实现都实现了_finalizeEnroll与_finalizeSignIn两个内部方法分别服务于注册第二因子和用第二因子登录两条路径。二、谁创建它TotpMultiFactorGenerator 工厂官方文档明确指出TotpMultiFactorAssertion只能由 TotpMultiFactorGenerator 提供具体来自它的两个静态工厂方法方法签名用途assertionForEnrollmentassertionForEnrollment(secret: TotpSecret, oneTimePassword: string): TotpMultiFactorAssertion完成 TOTP 第二因子的注册配合 MultiFactorUser.enroll 使用assertionForSignInassertionForSignIn(enrollmentId: string, oneTimePassword: string): TotpMultiFactorAssertion完成 TOTP 第二因子的登录配合 MultiFactorResolver.resolveSignIn 使用两者的差异集中在构造参数上注册场景传入TotpSecret——注册阶段服务端下发的共享密钥对象登录场景传入enrollmentId——用户在服务端已注册的 TOTP 因子的标识通常来自resolver.hints中选中的MultiFactorInfo.uid。从源码 totp.ts#L54-L78 可以看到这两个方法只是对内部实现的简单封装static assertionForEnrollment( secret: TotpSecret, oneTimePassword: string ): TotpMultiFactorAssertion { return TotpMultiFactorAssertionImpl._fromSecret(secret, oneTimePassword); } static assertionForSignIn( enrollmentId: string, oneTimePassword: string ): TotpMultiFactorAssertion { return TotpMultiFactorAssertionImpl._fromEnrollmentId( enrollmentId, oneTimePassword ); }此外TotpMultiFactorGenerator还提供了FACTOR_ID: totp静态常量FactorId.TOTP以及用于开启注册流程的generateSecret(session: MultiFactorSession): PromiseTotpSecret后面会展开。三、源码视角断言内部实现 TotpMultiFactorAssertionImpl虽然TotpMultiFactorAssertion接口本身是空壳但它的真正实现类是TotpMultiFactorAssertionImpl位于 packages/auth/src/mfa/assertions/totp.ts#L113-L176。它的构造函数同时容纳两种场景所需的信息export class TotpMultiFactorAssertionImpl extends MultiFactorAssertionImpl implements TotpMultiFactorAssertion { constructor( readonly otp: string, readonly enrollmentId?: string, readonly secret?: TotpSecret ) { super(FactorId.TOTP); } }即断言内部持有用户输入的 OTP、登录场景的enrollmentId、注册场景的secret。两个工厂方法分别构造不同的组合_fromSecret(secret, otp)→new TotpMultiFactorAssertionImpl(otp, undefined, secret)注册态_fromEnrollmentId(enrollmentId, otp)→new TotpMultiFactorAssertionImpl(otp, enrollmentId)登录态当用户把断言交给multiFactor(user).enroll(assertion)或resolver.resolveSignIn(assertion)时SDK 会调用基类 MultiFactorAssertionImpl._process根据当前MultiFactorSession的类型ENROLL还是SIGN_IN自动分发到_finalizeEnroll或_finalizeSignIn_finalizeEnroll会先断言secret必须存在否则抛auth/argument-error然后用secret._makeTotpVerificationInfo(otp)生成{ sessionInfo, verificationCode }调用finalizeEnrollTotpMfatotp.ts#L142-L157_finalizeSignIn会断言enrollmentId与otp都必须存在然后以{ mfaPendingCredential, mfaEnrollmentId, totpVerificationInfo: { verificationCode } }调用finalizeSignInTotpMfatotp.ts#L160-L175。这正是断言一词的含义它把用户的一次性密码与上下文绑定在合适的时间点消费掉。四、配合 TotpSecret注册断言的密钥来源注册场景的断言依赖TotpSecret见 auth.totpsecret.md它由TotpMultiFactorGenerator.generateSecret(session)产生封装了服务端返回的 TOTP 参数属性含义secretKey共享密钥/种子用于生成 OTP 与二维码hashingAlgorithm使用的哈希算法如SHA1codeLength一次性密码位数如 6codeIntervalSecondsOTP 刷新周期秒通常 30enrollmentCompletionDeadline注册完成的 UTC 截止时间字符串可用于倒计时提示generateSecret的源码实现totp.ts#L89-L105会先断言 session 中携带用户否则抛auth/internal-error然后向后端START_MFA_ENROLLMENT端点发送{ idToken, totpEnrollmentInfo: {} }并把响应的totpSessionInfo解析为TotpSecret。TotpSecret还提供generateQrCodeUrl(accountName?, issuer?)方法totp.ts#L256-L270生成符合 Key-Uri-Format 的otpauth://totp/...链接可直接渲染成二维码供 Google Authenticator 等 TOTP App 扫描。若未传参数SDK 默认使用当前用户邮箱作为accountName无用户时为unknownuser、Firebase App 名称作为issuer。该默认行为在单元测试 totp.test.ts#L305-L343 中有完整覆盖。五、实战流程一注册 TOTP 第二因子完整注册流程需要四步获取 multiFactorSession → 生成 TotpSecret 与二维码 → 用户扫码并输入动态码 → 构造断言并 enroll。仓库自带的 demo 应用 packages/auth/demo/src/index.js#L890-L952 给出了可直接参考的写法// 1. 为当前已登录用户创建 MFA 会话 const multiFactorSession await multiFactor(activeUser()).getSession(); // 2. 向服务端申请 TOTP 密钥并生成二维码链接 const totpSecret await TotpMultiFactorGenerator.generateSecret(multiFactorSession); const url totpSecret.generateQrCodeUrl(test, testissuer); console.log(TOTP URL is url); console.log(Finalize sign in by totpSecret.enrollmentCompletionDeadline); // 3. 用户用 TOTP App 扫码输入动态验证码后 const verificationCode $(#enroll-mfa-totp-verification-code).val(); const multiFactorAssertion TotpMultiFactorGenerator.assertionForEnrollment( totpSecret, verificationCode ); // 4. 完成注册displayName 可选用于标识该因子 await multiFactor(activeUser()).enroll(multiFactorAssertion, displayName);注意 demo 中还利用enrollmentCompletionDeadline做了每秒倒计时展示超时后提示 TOTP enrollment expired!这正是该字段的典型用途index.js#L903-L921。六、实战流程二用 TOTP 第二因子完成登录当用户已注册 TOTP 但尚未通过第二因子验证时首次登录如signInWithEmailAndPassword会抛出auth/multi-factor-auth-required错误。此时应通过getMultiFactorResolver获取resolver用resolver.hints让用户选择要使用的 TOTP 因子再构造登录断言import { getMultiFactorResolver, TotpMultiFactorGenerator } from firebase/auth; signInWithEmailAndPassword(auth, email, password).catch((error) { if (error.code auth/multi-factor-auth-required) { const resolver getMultiFactorResolver(auth, error); // resolver.hints 中包含已注册因子找到 TOTP 因子后取其 uid const selectedMultiFactorHint resolver.hints[0]; // 用户输入 TOTP App 中的动态码后 const otp $(#multi-factor-totp-sign-in-verification-code).val(); const assertion TotpMultiFactorGenerator.assertionForSignIn( selectedMultiFactorHint.uid, // 即 enrollmentId otp ); resolver.resolveSignIn(assertion).then((userCredential) { // 登录成功userCredential.user 为已通过双因子验证的用户 }); } });该流程与 demo 中的 onFinalizeSignInWithTotpMultiFactor 完全一致其底层行为在集成测试 packages/auth/test/integration/flows/totp.test.ts 中有端到端验证。七、底层 API 调用链与请求结构断言最终都要落到 Firebase Auth REST API 上相关定义位于 packages/auth/src/api/account_management/mfa.ts 与 packages/auth/src/api/authentication/mfa.ts阶段端点关键请求字段生成密钥START_MFA_ENROLLMENTstartEnrollTotpMfaidToken、totpEnrollmentInfo完成注册FINALIZE_MFA_ENROLLMENTfinalizeEnrollTotpMfaidToken、displayName?、totpVerificationInfo: { sessionInfo, verificationCode }完成登录FINALIZE_MFA_SIGN_INfinalizeSignInTotpMfamfaPendingCredential、mfaEnrollmentId、totpVerificationInfo: { verificationCode }其中StartTotpMfaEnrollmentResponse的totpSessionInfo结构mfa.ts#L120-L129包含sharedSecretKey、verificationCodeLength、hashingAlgorithm、periodSec、sessionInfo、finalizeEnrollmentTime六个字段正是第四节TotpSecret各属性的直接来源。单元测试 totp.test.ts 精确断言了这些请求体。例如注册断言被_process消费后发出的请求体必须严格等于{ idToken: enrollment-id-token, totpVerificationInfo: { verificationCode: 123456, sessionInfo: verification-id } }而登录断言发出的请求体为{ mfaPendingCredential: mfa-pending-credential, mfaEnrollmentId: enrollment-id, totpVerificationInfo: { verificationCode: 123456 } }八、错误处理与边界情况从实现与测试中可以确认以下边界行为注册态缺少 secret_finalizeEnroll对secret做_assert缺失时抛auth/argument-error登录态缺少 enrollmentId 或 otp_finalizeSignIn同样抛auth/argument-error对应测试见 totp.test.ts#L254-L274session 缺少用户generateSecret抛auth/internal-errortotp.test.ts#L87-L97OTP 过期注册有时间窗口enrollmentCompletionDeadline可用于前端倒计时并在过期后终止流程错误的动态码注册/登录请求会被后端拒绝并返回相应 Firebase Auth 错误码断言本身不缓存任何状态可安全地根据新 OTP 重新构造。九、总结TotpMultiFactorAssertion虽是一个空接口却是 Firebase JS SDK TOTP MFA 两条核心流程注册与二次登录的统一入口它由TotpMultiFactorGenerator的两个静态工厂方法构造内部由TotpMultiFactorAssertionImpl依据会话类型分别驱动FINALIZE_MFA_ENROLLMENT与FINALIZE_MFA_SIGN_IN两个后端端点。理解这个断言对象的产生方式与消费链路是正确接入 Firebase Auth TOTP 多因子认证的关键。相关类型定义集中在 packages/auth/src/model/public_types.ts#L1273完整实现与测试可分别查看 packages/auth/src/mfa/assertions/totp.ts 与 packages/auth/src/mfa/assertions/totp.test.ts。赞分享开发工具后端【免费下载链接】firebase-js-sdkFirebase Javascript SDK项目地址https://gitcode.com/gh_mirrors/fi/firebase-js-sdk点击查看免费下载相关推荐Firebase JS SDK 手机号第二因素登录PhoneSingleFactorInfoOptions 与 PhoneMultiFactorSignInInfoOptions 实战指南Firebase JS SDK 手机号第二因素登录PhoneSingleFactorInfoOptions 与 PhoneMultiFactorSignInI开发工具后端Firebase JS SDK 多因素认证核心接口 MultiFactorAssertion 深度解析factorId 属性、实现原理与注册/登录实战Firebase JS SDK 多因素认证核心接口 MultiFactorAssertion 深度解析factorId 属性、实现原理与注册/登录实战 本文围开发工具后端Firebase Authfirebase-js-sdkPhoneMultiFactorSignInInfoOptions 详解手机号第二因素登录参数配置与实现原理Firebase Authfirebase js sdkPhoneMultiFactorSignInInfoOptions 详解手机号第二因素登录参数配置开发工具后端上一篇GreaterWMS开源仓库管理系统企业级仓储数字化解决方案下一篇DayZ终极离线生存指南为什么你需要这个完整的单机体验创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站