diff --git a/src/components/AuthorizerVerifyOtp.tsx b/src/components/AuthorizerVerifyOtp.tsx index af5357d..4a6c5ae 100644 --- a/src/components/AuthorizerVerifyOtp.tsx +++ b/src/components/AuthorizerVerifyOtp.tsx @@ -35,6 +35,7 @@ export const AuthorizerVerifyOtp: FC<{ const [loading, setLoading] = useState(false); const [totpData, setTotpData] = useState({ ...initTotpData }); const [sendingOtp, setSendingOtp] = useState(false); + const [isLockedOut, setIsLockedOut] = useState(false); const [formData, setFormData] = useState({ otp: null, }); @@ -68,6 +69,19 @@ export const AuthorizerVerifyOtp: FC<{ data.is_totp = !!is_totp; const { data: res, errors } = await authorizerRef.verifyOtp(data); if (errors && errors.length) { + if (errors[0]?.code === 'TOO_MANY_REQUESTS') { + setIsLockedOut(true); + // Fall back to a fixed message if the server ever sends an empty + // one: the form is about to go fully disabled (input + submit), + // so this is the user's only explanation for why - an empty + // string here would mean no message renders at all (Message + // returns null for blank text) and the form goes silently dead. + setError( + errors[0]?.message || + `Too many attempts. Please wait a while before trying again.`, + ); + return; + } setError(errors[0]?.message || ``); return; } @@ -184,7 +198,11 @@ export const AuthorizerVerifyOtp: FC<{ /> )} {error && ( - + )}

Please enter the OTP sent to your email or phone number or authenticator @@ -203,8 +221,10 @@ export const AuthorizerVerifyOtp: FC<{ }`} placeholder="e.g.- AB123C" type="password" + autoComplete="one-time-code" value={formData.otp || ''} onChange={(e) => onInputChange('otp', e.target.value)} + disabled={isLockedOut} /> {errorData.otp && (

{errorData.otp}
@@ -222,7 +242,7 @@ export const AuthorizerVerifyOtp: FC<{
{loading ? `Processing ...` : `Submit`} @@ -230,13 +250,14 @@ export const AuthorizerVerifyOtp: FC<{ {setView && ( - {sendingOtp ? ( -
Sending ...
- ) : ( - - Resend OTP - - )} + {!is_totp && + (sendingOtp ? ( +
Sending ...
+ ) : ( + + Resend OTP + + ))} {config.is_sign_up_enabled && (
Don't have an account?{' '}