Skip to content

Commit ae45337

Browse files
authored
fix: improve Setup MFA Flow for Superusers (#1545)
1 parent 071e5c9 commit ae45337

File tree

8 files changed

+81
-88
lines changed

8 files changed

+81
-88
lines changed

components/guards/SetupMFA.tsx

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,12 @@ const SetupMFA = () => {
2929
const userVerifiedEmail = useTypedSelector((state) => state.user.verifiedEmail);
3030

3131
const [phoneNumber, setPhoneNumber] = useState('');
32+
const [storedPhoneNumber, setStoredPhoneNumber] = useState('');
3233
const [verificationId, setVerificationId] = useState('');
3334
const [verificationCode, setVerificationCode] = useState('');
3435
const [error, setError] = useState('');
36+
const [emailVerificationSent, setEmailVerificationSent] = useState(false);
37+
const [emailVerificationSuccess, setEmailVerificationSuccess] = useState('');
3538
const [showReauth, setShowReauth] = useState(false);
3639
const [password, setPassword] = useState('');
3740
const [isReauthenticating, setIsReauthenticating] = useState(false);
@@ -51,6 +54,20 @@ const SetupMFA = () => {
5154
};
5255
}, []);
5356

57+
// Store phone number when user enters it
58+
useEffect(() => {
59+
if (phoneNumber && !storedPhoneNumber) {
60+
setStoredPhoneNumber(phoneNumber);
61+
}
62+
}, [phoneNumber, storedPhoneNumber]);
63+
64+
// Restore phone number after reauthentication
65+
useEffect(() => {
66+
if (!showReauth && storedPhoneNumber && !phoneNumber) {
67+
setPhoneNumber(storedPhoneNumber);
68+
}
69+
}, [showReauth, storedPhoneNumber, phoneNumber]);
70+
5471
const handleReauthentication = async () => {
5572
if (!password.trim()) {
5673
setError(t('form.passwordRequired'));
@@ -67,7 +84,7 @@ const SetupMFA = () => {
6784
// Reset the MFA setup process
6885
setVerificationId('');
6986
setVerificationCode('');
70-
setPhoneNumber('');
87+
// Don't reset phone number - it will be restored from storedPhoneNumber
7188
} catch (error: any) {
7289
rollbar.error('Reauthentication error:', error);
7390
if (error.code === 'auth/wrong-password') {
@@ -81,6 +98,7 @@ const SetupMFA = () => {
8198
setIsReauthenticating(false);
8299
}
83100
};
101+
84102
const handleEnrollMFA = async () => {
85103
if (!userVerifiedEmail) {
86104
setError(t('form.emailNotVerified'));
@@ -126,16 +144,20 @@ const SetupMFA = () => {
126144

127145
const handleSendVerificationEmail = async () => {
128146
setError('');
147+
setEmailVerificationSuccess('');
129148
const user = auth.currentUser;
130149
if (user) {
131150
const { error } = await sendVerificationEmail(user);
132151
if (error) {
152+
if (error.code === 'auth/too-many-requests') {
153+
setError(t('form.firebase.tooManyAttempts'));
154+
} else {
155+
setError(t('form.emailVerificationError'));
156+
}
133157
rollbar.error('Send verification email error:', error);
134-
setError(t('form.emailVerificationError'));
135158
} else {
136-
// Show success message instead of error
137-
setError('');
138-
// You might want to show a success state here instead
159+
setEmailVerificationSent(true);
160+
setEmailVerificationSuccess(t('form.emailVerificationSent'));
139161
}
140162
}
141163
};
@@ -188,19 +210,31 @@ const SetupMFA = () => {
188210
</Box>
189211
);
190212
}
213+
191214
return (
192215
<Box>
193216
<Typography variant="h3">{t('setupMFA.title')}</Typography>
194217
{!userVerifiedEmail ? (
195218
<Box>
196219
<Typography>{t('form.emailNotVerified')}</Typography>
220+
{emailVerificationSuccess && (
221+
<Alert severity="success" sx={{ mt: 2, mb: 2 }}>
222+
{emailVerificationSuccess}
223+
<Typography variant="body2" sx={{ mt: 1 }}>
224+
{t('form.emailVerificationSpamCheck')}
225+
</Typography>
226+
</Alert>
227+
)}
197228
<Button
198229
variant="contained"
199230
color="secondary"
200231
sx={{ ...buttonStyle, mt: 2 }}
201232
onClick={handleSendVerificationEmail}
233+
disabled={emailVerificationSent}
202234
>
203-
{t('form.sendVerificationEmail')}
235+
{emailVerificationSent
236+
? t('form.resendVerificationEmail')
237+
: t('form.sendVerificationEmail')}
204238
</Button>
205239
</Box>
206240
) : !verificationId ? (

cypress/integration/tests/superadmin-mfa.cy.tsx

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -122,29 +122,10 @@ describe('Superadmin MFA Flow', () => {
122122

123123
// We can't mock the reCAPTCHA in Cypress, so we will skip this step that tests the actual sms sending and mfa setup
124124

125-
// Mock Firebase MFA enrollment endpoints
126-
// cy.intercept('POST', '**/identitytoolkit.googleapis.com/v2/accounts/mfaEnrollment:start*', {
127-
// statusCode: 200,
128-
// body: {
129-
// phoneSessionInfo: {
130-
// sessionInfo: 'mock-session-info',
131-
// },
132-
// },
133-
// }).as('mfaEnrollmentStart');
134-
135-
// cy.intercept('POST', '**/identitytoolkit.googleapis.com/v2/accounts/mfaEnrollment:finalize*', {
136-
// statusCode: 200,
137-
// body: {
138-
// idToken: 'mock-id-token',
139-
// refreshToken: 'mock-refresh-token',
140-
// },
141-
// }).as('mfaEnrollmentFinalize');
142125
// // Enter verification code
143126
// cy.get('input[id="verificationCode"]').should('be.visible').type(testVerificationCode);
144127
// cy.get('button').contains('Verify Code').click();
145128

146-
// cy.wait('@mfaEnrollmentFinalize');
147-
148129
// // Should redirect to admin dashboard
149130
// cy.url().should('include', '/admin/dashboard');
150131
// cy.get('h2').should('contain', 'Superadmin dashboard');

i18n/messages/auth/de.json

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,20 @@
6161
"emailNotVerified": "Bitte verifiziere deine E-Mail-Adresse, bevor du die Zwei-Faktor-Authentifizierung einrichtest.",
6262
"emailVerificationError": "Fehler beim Senden der Verifizierungs-E-Mail. Bitte versuche es erneut.",
6363
"emailVerificationSent": "Verifizierungs-E-Mail wurde gesendet. Bitte überprüfe deinen Posteingang.",
64-
"sendVerificationEmail": "Verifizierungs-E-Mail senden",
64+
"emailVerificationSpamCheck": "Wenn du die E-Mail nicht siehst, überprüfe bitte deinen Spam-Ordner.",
65+
"sendVerificationEmail": "Verifizierungs-e-mail senden",
66+
"resendVerificationEmail": "Verifizierungs-e-mail erneut senden",
6567
"passwordRequired": "Passwort ist für die erneute Authentifizierung erforderlich.",
6668
"reauthenticationError": "Erneute Authentifizierung fehlgeschlagen. Bitte versuche es erneut."
6769
},
6870
"verifyMFA": {
69-
"title": "Zwei-Faktor-Authentifizierung verifizieren",
70-
"triggerSMS": "SMS-Code senden",
71+
"title": "Zwei-faktor-authentifizierung verifizieren",
72+
"triggerSMS": "SMS-code senden",
7173
"verifyCode": "Code verifizieren",
7274
"phoneNumber": "Wir senden einen Verifizierungscode an Ihre registrierte Telefonnummer: {phoneNumber}"
7375
},
7476
"setupMFA": {
75-
"title": "Zwei-Faktor-Authentifizierung einrichten",
76-
"pageTitle": "Sichern Sie Ihr Konto",
77+
"title": "Zwei-faktor-authentifizierung einrichten",
7778
"sendCode": "Verifizierungscode senden",
7879
"verifyCode": "Code verifizieren",
7980
"enterCodeHelperText": "Bitte geben Sie den Verifizierungscode ein, den wir an Ihr Telefon gesendet haben:",
@@ -82,11 +83,6 @@
8283
"cancelReauth": "Abbrechen",
8384
"confirmReauth": "Bestätigen",
8485
"reauthenticating": "Bestätige..."
85-
},
86-
"verifyEmail": {
87-
"pageTitle": "E-Mail-Adresse verifizieren",
88-
"instructions": "Bitte überprüfe deine E-Mails und klicke auf den Verifizierungslink, um fortzufahren.",
89-
"sendButton": "Verifizierungs-E-Mail erneut senden"
9086
}
9187
}
9288
}

i18n/messages/auth/en.json

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@
5151
"expiredCode": "This reset password link is now expired, please <resetLink>restart the process</resetLink> and try again.",
5252
"getUserError": "There was an error retrieving your account. Try again later and <contactLink>message the Bloom team</contactLink> if you're still getting this error."
5353
},
54-
"phoneNumberLabel": "Phone Number",
55-
"verificationCodeLabel": "Verification Code",
54+
"phoneNumberLabel": "Phone number",
55+
"verificationCodeLabel": "Verification code",
5656
"mfaTriggerError": "Error sending SMS code. Please try again.",
5757
"mfaVerificationIdMissing": "Please request an SMS code first.",
5858
"mfaEnrollError": "Error enrolling in 2FA. Please try again.",
@@ -61,32 +61,30 @@
6161
"emailNotVerified": "Please verify your email before setting up 2FA.",
6262
"emailVerificationError": "Error sending verification email. Please try again.",
6363
"emailVerificationSent": "Verification email sent. Please check your inbox.",
64+
"emailVerificationSpamCheck": "If you don't see the email, please check your spam folder.",
6465
"sendVerificationEmail": "Send Verification Email",
66+
"resendVerificationEmail": "Resend Verification Email",
67+
"sendVerificationEmail": "Send verification email",
68+
"resendVerificationEmail": "Resend verification email",
6569
"passwordRequired": "Password is required for reauthentication.",
6670
"reauthenticationError": "Failed to reauthenticate. Please try again."
6771
},
6872
"verifyMFA": {
69-
"title": "Verify Two-Factor Authentication",
70-
"triggerSMS": "Send SMS Code",
71-
"verifyCode": "Verify Code",
73+
"title": "Verify two-factor authentication",
74+
"triggerSMS": "Send SMS code",
75+
"verifyCode": "Verify code",
7276
"phoneNumber": "We will send a verification code to your registered phone number: {phoneNumber}"
7377
},
7478
"setupMFA": {
75-
"title": "Set up Two-Factor Authentication",
76-
"pageTitle": "Secure Your Account",
77-
"sendCode": "Send Verification Code",
78-
"verifyCode": "Verify Code",
79+
"title": "Set up two-factor authentication",
80+
"sendCode": "Send verification code",
81+
"verifyCode": "Verify code",
7982
"enterCodeHelperText": "Please enter the verification code we sent to your phone:",
8083
"reauthTitle": "Confirm your password",
8184
"reauthDescription": "Please enter your password before continuing",
8285
"cancelReauth": "Cancel",
8386
"confirmReauth": "Confirm",
8487
"reauthenticating": "Confirming..."
85-
},
86-
"verifyEmail": {
87-
"pageTitle": "Verify Your Email",
88-
"instructions": "Please check your email and click the verification link to continue.",
89-
"sendButton": "Resend Verification Email"
9088
}
9189
}
9290
}

i18n/messages/auth/es.json

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@
6161
"emailNotVerified": "Por favor, verifica tu email antes de configurar la autenticación de dos factores.",
6262
"emailVerificationError": "Error al enviar el email de verificación. Por favor, inténtalo de nuevo.",
6363
"emailVerificationSent": "Email de verificación enviado. Por favor, revisa tu bandeja de entrada.",
64+
"emailVerificationSpamCheck": "Si no ves el email, por favor revisa tu carpeta de spam.",
6465
"sendVerificationEmail": "Enviar email de verificación",
66+
"resendVerificationEmail": "Reenviar email de verificación",
6567
"passwordRequired": "Se requiere contraseña para la reautenticación.",
6668
"reauthenticationError": "Error al reautenticar. Por favor, inténtalo de nuevo."
6769
},
@@ -73,7 +75,6 @@
7375
},
7476
"setupMFA": {
7577
"title": "Configurar autenticación de dos factores",
76-
"pageTitle": "Asegura tu cuenta",
7778
"sendCode": "Enviar código de verificación",
7879
"verifyCode": "Verificar código",
7980
"enterCodeHelperText": "Por favor, introduce el código de verificación que hemos enviado a tu teléfono:",
@@ -82,11 +83,6 @@
8283
"cancelReauth": "Cancelar",
8384
"confirmReauth": "Confirmar",
8485
"reauthenticating": "Confirmando..."
85-
},
86-
"verifyEmail": {
87-
"pageTitle": "Verifica tu email",
88-
"instructions": "Por favor, revisa tu email y haz clic en el enlace de verificación para continuar.",
89-
"sendButton": "Reenviar email de verificación"
9086
}
9187
}
9288
}

i18n/messages/auth/fr.json

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@
6161
"emailNotVerified": "Veuillez vérifier votre email avant de configurer l'authentification à deux facteurs.",
6262
"emailVerificationError": "Erreur lors de l'envoi de l'email de vérification. Veuillez réessayer.",
6363
"emailVerificationSent": "Email de vérification envoyé. Veuillez vérifier votre boîte de réception.",
64+
"emailVerificationSpamCheck": "Si vous ne voyez pas l'email, veuillez vérifier votre dossier spam.",
6465
"sendVerificationEmail": "Envoyer l'email de vérification",
66+
"resendVerificationEmail": "Renvoyer l'email de vérification",
6567
"passwordRequired": "Le mot de passe est requis pour la réauthentification.",
6668
"reauthenticationError": "Échec de la réauthentification. Veuillez réessayer."
6769
},
@@ -74,7 +76,6 @@
7476
},
7577
"setupMFA": {
7678
"title": "Configurer l'authentification à deux facteurs",
77-
"pageTitle": "Sécurisez votre compte",
7879
"sendCode": "Envoyer le code de vérification",
7980
"verifyCode": "Vérifier le code",
8081
"enterCodeHelperText": "Veuillez entrer le code de vérification que nous avons envoyé à votre téléphone :",
@@ -83,11 +84,6 @@
8384
"cancelReauth": "Annuler",
8485
"confirmReauth": "Confirmer",
8586
"reauthenticating": "Confirmation..."
86-
},
87-
"verifyEmail": {
88-
"pageTitle": "Vérifiez votre email",
89-
"instructions": "Veuillez vérifier votre email et cliquer sur le lien de vérification pour continuer.",
90-
"sendButton": "Renvoyer l'email de vérification"
9187
}
9288
}
9389
}

i18n/messages/auth/hi.json

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@
5151
"expiredCode": "This reset password link is now expired, please <resetLink>restart the process</resetLink> and try again.",
5252
"getUserError": "Aapka account retrieve karne mein error aa raha hai. Baad mein dubara prayas kariye aur <contactLink>Bloom team ko message kariye</contactLink> agar aapko fir bhi error aa raha hai. "
5353
},
54-
"phoneNumberLabel": "Phone Number",
55-
"verificationCodeLabel": "Verification Code",
54+
"phoneNumberLabel": "Phone number",
55+
"verificationCodeLabel": "Verification code",
5656
"mfaTriggerError": "SMS code bhejne mein truti. Kripya punah prayaas karein.",
5757
"mfaVerificationIdMissing": "Kripya pehle SMS code ka anuroodh karein.",
5858
"mfaEnrollError": "2FA mein naamaakon karne mein truti. Kripya punah prayaas karein.",
@@ -61,32 +61,28 @@
6161
"emailNotVerified": "2FA setup karne se pehle kripya apne email ki pushti karein.",
6262
"emailVerificationError": "Satyaapan email bhejne mein truti. Kripya punah prayaas karein.",
6363
"emailVerificationSent": "Satyaapan email bhej diya gaya hai. Kripya apne inbox ki jaanch karein.",
64-
"sendVerificationEmail": "Satyaapan Email Bhejein",
64+
"emailVerificationSpamCheck": "Agar aapko email nahi dikh raha, kripya apne spam folder ki jaanch karein.",
65+
"sendVerificationEmail": "Satyaapan email bhejein",
66+
"resendVerificationEmail": "Satyaapan email punah bhejein",
6567
"passwordRequired": "Punah praman ke liye password aavashyak hai.",
6668
"reauthenticationError": "Punah praman mein asafalta. Kripya punah prayaas karein."
6769
},
6870
"verifyMFA": {
69-
"title": "Do-Charan Praman Verify Karein",
70-
"triggerSMS": "SMS Code Bhejein",
71-
"verifyCode": "Code Verify Karein",
71+
"title": "Do-charan praman verify karein",
72+
"triggerSMS": "SMS code bhejein",
73+
"verifyCode": "Code verify karein",
7274
"phoneNumber": "Hum aapke registered phone number par ek verification code bhejenge: {phoneNumber}"
7375
},
7476
"setupMFA": {
75-
"title": "Do-Charan Praman Setup Karein",
76-
"pageTitle": "Apne Khaate ko Surakshit Karein",
77-
"sendCode": "Verification Code Bhejein",
78-
"verifyCode": "Code Verify Karein",
77+
"title": "Do-charan praman setup karein",
78+
"sendCode": "Verification code bhejein",
79+
"verifyCode": "Code verify karein",
7980
"enterCodeHelperText": "Kripya apne phone par bheje gaye verification code ko darj karein:",
8081
"reauthTitle": "Apni Pehchaan Confirm Karein",
8182
"reauthDescription": "Kripya aage badhne se pehle apna password darj karein",
8283
"cancelReauth": "Cancel Karein",
8384
"confirmReauth": "Confirm Karein",
8485
"reauthenticating": "Confirm kar rahe hain..."
85-
},
86-
"verifyEmail": {
87-
"pageTitle": "Apna Email Verify Karein",
88-
"instructions": "Kripya apne email ki jaanch karein aur jaari rakhne ke liye satyaapan link par click karein.",
89-
"sendButton": "Satyaapan Email Punah Bhejein"
9086
}
9187
}
9288
}

i18n/messages/auth/pt.json

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,32 +61,28 @@
6161
"emailNotVerified": "Por favor, verifique seu e-mail antes de configurar a autenticação de dois fatores.",
6262
"emailVerificationError": "Erro ao enviar e-mail de verificação. Por favor, tente novamente.",
6363
"emailVerificationSent": "E-mail de verificação enviado. Por favor, verifique sua caixa de entrada.",
64+
"emailVerificationSpamCheck": "Se você não vir o e-mail, verifique sua pasta de spam.",
6465
"sendVerificationEmail": "Enviar e-mail de verificação",
66+
"resendVerificationEmail": "Reenviar e-mail de verificação",
6567
"passwordRequired": "Senha é necessária para reautenticação.",
6668
"reauthenticationError": "Falha na reautenticação. Por favor, tente novamente."
6769
},
6870
"verifyMFA": {
69-
"title": "Verificar Autenticação de Dois Fatores",
70-
"triggerSMS": "Enviar Código SMS",
71-
"verifyCode": "Verificar Código",
71+
"title": "Verificar autenticação de dois fatores",
72+
"triggerSMS": "Enviar código SMS",
73+
"verifyCode": "Verificar código",
7274
"phoneNumber": "Enviaremos um código de verificação para o seu número de telefone registrado: {phoneNumber}"
7375
},
7476
"setupMFA": {
75-
"title": "Configurar Autenticação de Dois Fatores",
76-
"pageTitle": "Proteja sua Conta",
77-
"sendCode": "Enviar Código de Verificação",
78-
"verifyCode": "Verificar Código",
77+
"title": "Configurar autenticação de dois fatores",
78+
"sendCode": "Enviar código de verificação",
79+
"verifyCode": "Verificar código",
7980
"enterCodeHelperText": "Por favor, digite o código de verificação que enviamos para o seu telefone:",
8081
"reauthTitle": "Confirme sua Identidade",
8182
"reauthDescription": "Por favor digite sua senha antes de continuar",
8283
"cancelReauth": "Cancelar",
8384
"confirmReauth": "Confirmar",
8485
"reauthenticating": "Confirmando..."
85-
},
86-
"verifyEmail": {
87-
"pageTitle": "Verifique seu e-mail",
88-
"instructions": "Por favor, verifique seu e-mail e clique no link de verificação para continuar.",
89-
"sendButton": "Reenviar e-mail de verificação"
9086
}
9187
}
9288
}

0 commit comments

Comments
 (0)