使用Cognito与Amplify重发短信MFA时会话刷新异常问题求助
核心问题根源
- API调用错误:你使用的
Auth.resendSignUp()是用户注册阶段重发注册确认码的接口,不适用于登录流程中OTP挑战过期的场景。调用该接口生成的新验证码和你当前登录流程的会话没有绑定关系,因此提交验证码时仍然使用旧的过期会话,就会返回Invalid session报错。 - 会话未更新:你没有将重发验证码后生成的新会话存储下来,提交OTP时仍然使用第一次登录返回的过期会话对象。
- 测试逻辑场景错误:
Auth.currentAuthenticatedUser()、refreshSession等接口仅适用于用户已完成全部登录认证后的场景,你处于OTP挑战阶段时用户并未完成登录,根本无法获取到有效认证用户对象,这部分逻辑完全不适用于当前场景。
正确实现方案
步骤1:调整登录逻辑,存储有效会话
首次调用Auth.signIn触发OTP挑战后,需要将返回的包含会话信息的user对象存入state,后续重发验证码、提交OTP都需要使用这个对象:
async componentDidMount() { const username = "yyy"; const password = "zzz"; const user = await Auth.signIn(username, password); // 存储登录阶段的user对象(包含有效会话) this.setState({ signInUser: user, username }); const { challengeName } = user; if (!challengeName) { const { history } = this.props; history.push("/", { err: "No current user" }); } }
步骤2:替换重发验证码逻辑
使用Amplify专门提供的登录挑战重发接口Auth.resendSignInChallenge,不需要用户重新输入密码即可生成新的有效会话和验证码:
resendConfirmationCode = async (e) => { try { // 传入之前存储的登录阶段user对象 const newUser = await Auth.resendSignInChallenge(this.state.signInUser); // 更新state中的user对象,替换为新的有效会话 this.setState({ signInUser: newUser }); console.log("code resent successfully"); this.resetTimer(); } catch (err) { console.log("error resending code: ", err); } };
步骤3:调整OTP提交逻辑
提交验证码时必须传入state中最新的包含有效会话的user对象:
submitOTP = async (otpCode) => { try { // 传入最新的signInUser对象,不可使用首次登录生成的过期对象 await Auth.confirmSignIn(this.state.signInUser, otpCode); // 登录成功后的跳转逻辑 this.props.history.push("/dashboard"); } catch (err) { console.log("OTP验证失败", err); } }
额外注意事项
- Cognito登录挑战的会话有效期固定为3分钟,过期后必须生成新的会话才能完成验证
- 不要混用注册阶段和登录阶段的接口,两类接口的会话体系完全独立,互不兼容
内容的提问来源于stack exchange,提问作者Eric Mitjans
相关产品推荐
相关产品推荐

