fix: setupTotp() clobbering mfa_confirmed_at breaks login MFA check
When MFA was already enabled and the user clicked "Opnieuw instellen" on the TOTP card, setupTotp() unconditionally set mfa_confirmed_at to null. If the user then cancelled the dialog without confirming, the login controller's check `mfa_enabled && mfa_confirmed_at` evaluated to false (true && null), silently skipping the MFA challenge. Fix: only set mfa_method and mfa_confirmed_at when MFA is not yet enabled (first-time setup). For re-setup or adding TOTP as a second method, only rotate the mfa_secret — matching the guard already applied to setupEmail(). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -34,16 +34,22 @@ final class MfaService
|
||||
/**
|
||||
* Begin TOTP setup: generate a secret and return QR code data.
|
||||
* MFA is NOT yet active — user must confirm with a valid code.
|
||||
* If MFA is already enabled (re-setup or adding as second method),
|
||||
* only the secret is rotated — confirmed_at and preferred method
|
||||
* are preserved so a cancelled setup doesn't break the login flow.
|
||||
*/
|
||||
public function setupTotp(User $user): array
|
||||
{
|
||||
$secret = $this->google2fa->generateSecretKey(32);
|
||||
|
||||
$user->update([
|
||||
'mfa_secret' => encrypt($secret),
|
||||
'mfa_method' => MfaMethod::TOTP->value,
|
||||
'mfa_confirmed_at' => null,
|
||||
]);
|
||||
$updateData = ['mfa_secret' => encrypt($secret)];
|
||||
|
||||
if (! $user->mfa_enabled) {
|
||||
$updateData['mfa_method'] = MfaMethod::TOTP->value;
|
||||
$updateData['mfa_confirmed_at'] = null;
|
||||
}
|
||||
|
||||
$user->update($updateData);
|
||||
|
||||
$qrCodeUrl = $this->google2fa->getQRCodeUrl(
|
||||
company: 'Crewli',
|
||||
|
||||
Reference in New Issue
Block a user