Rank 1: Thread
MFA TOTP State Inconsistency After Disable/Re-enable Flow — Invalid Token During Verification
Environment:
- Next.js
- node-appwrite
- Session-based authentication
- TOTP MFA
Initially, my MFA disable flow was:
await account.updateMFA({ mfa: false });
await account.deleteMFAAuthenticator({ type: AuthenticatorType.Totp,});After running this flow, listMFAFactors() still returned:
{ "totp": true, "phone": false, "email": true, "recoveryCode": true}Observed behavior:
- UI still showed MFA enabled
- Recovery codes remained available
- MFA appeared disabled internally but factor state still remained active
Then I changed the disable flow order to:
await account.deleteMFAAuthenticator({ type: AuthenticatorType.Totp,});
await account.updateMFA({ mfa: false });After this change, listMFAFactors() correctly returned:
{ "totp": false, "phone": false, "email": true, "recoveryCode": true}and the UI correctly showed MFA disabled.
However, after this flow change, MFA could no longer be re-enabled successfully.
My enable flow is:
createMFAAuthenticator()- Scan QR code
- Enter OTP
updateMFAAuthenticator()createMFARecoveryCodes()updateMFA({ mfa: true })
The failure happens exactly at:
await account.updateMFAAuthenticator({ type: AuthenticatorType.Totp, otp,});with the error:
Invalid token passed in the request.Important details:
- QR code is freshly generated
- OTP is valid
- OTP entered within ~10 seconds
- Session is valid
- Authenticator app is synced correctly
- Error started only after changing the disable flow order
Before changing the flow order:
- MFA could still be re-enabled
- but factor state remained inconsistent (
totp: true)
After changing the flow order:
- factor state became correct (
totp: false) - but OTP verification permanently fails