Firebase重发OTP时重复发送旧验证码且验证失败问题
Firebase Auth OTP重发验证失败问题解决方案
问题核心原因
- 重发OTP后未更新验证用的
confirmObj(即signInWithPhoneNumber返回的会话对象),导致验证时仍使用旧的verificationId,与新发送的OTP不匹配。 - 首次OTP会话过期(Firebase默认有效期约5分钟),旧
verificationId失效,新OTP对应新会话,代码未同步更新会话信息。 - 全局
window.recaptchaVerifier被重复覆盖,可能导致实例冲突。
解决方案
1. 重发OTP时更新验证会话对象
在组件状态中维护confirmObj,重发OTP时将新获取的会话对象赋值给它,确保验证时使用最新会话:
const handleReSendOtp = async () => { setOtp(""); setOtpError(false); setIsSubmitting(true); try { // 获取新的OTP会话对象 const newConfirmObj = await setUpRecaptcha( "another-reCaptcha-container", userMobileNo ); if (newConfirmObj?.verificationId) { // 更新组件中的会话对象状态 setConfirmObj(newConfirmObj); setMinutes(0); setSeconds(45); openSnackbarFunction(dispatch, "验证码已重新发送", "info"); grecaptcha?.reset(); setIsSubmitting(false); } } catch (error: any) { console.log(error); if (error?.code === "auth/too-many-requests") { openSnackbarFunction(dispatch, "请求次数过多,请稍后再试", "error"); } else { openSnackbarFunction(dispatch, String(error), "error"); } setIsSubmitting(false); navigate(Paths.WELCOME); } };
2. 优化reCAPTCHA实例管理
避免全局变量冲突,每次创建新实例前销毁旧实例:
export const setUpRecaptcha = async ( recaptchaContainer: string, number: string ) => { // 清理旧的reCAPTCHA实例 if (window.recaptchaVerifier) { window.recaptchaVerifier.clear(); } // 创建新实例 const recaptchaVerifier = new RecaptchaVerifier( recaptchaContainer, { size: "invisible", }, auth ); const verificationToken = await recaptchaVerifier.verify(); if (verificationToken) { return signInWithPhoneNumber(auth, number, recaptchaVerifier); } };
3. 新增会话过期错误处理
在OTP验证逻辑中捕获auth/session-expired错误,明确提示用户重新获取OTP:
catch (error: any) { console.log(error, "error message"); if (error?.code === "auth/invalid-verification-code") { openSnackbarFunction( dispatch, "输入的验证码不正确", "error" ); } else if (error?.code === "auth/session-expired") { openSnackbarFunction( dispatch, "验证码会话已过期,请重新获取", "error" ); } else if (error?.code === "auth/invalid-app-credential") { openSnackbarFunction( dispatch, "出现错误,请重试", "error" ); navigate(Paths.WELCOME); } else { openSnackbarFunction(dispatch, String(error), "error"); } setOtpError(true); setIsSubmitting(false); }
关键注意事项
- 每次请求OTP(首次/重发)必须使用返回的新
confirmObj验证,每个verificationId仅对应一次有效会话。 - Firebase OTP会话默认有效期约5分钟,过期后旧会话无法验证任何OTP,必须重新请求。
- 重发OTP时确保reCAPTCHA实例正确重置,避免旧实例干扰新请求。
内容的提问来源于stack exchange,提问作者Shubham Chaudhary
相关产品推荐
相关产品推荐

