From 7e07f6b95814f7a2b4356db541b71edafcaaf597 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 6 May 2024 17:43:34 -0700 Subject: [PATCH] feat(auth): ensure user isn't kicked out after enabling MFA User's were kicked out and forced to verify their session after enabling MFA if they already had factors enabled. This change ensures that they are not kicked out of their current session after MFA is enabled by adding all relevant factors to the session. --- app/controllers/api/account.php | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 500b0842ab..b57b7cb891 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -3495,14 +3495,33 @@ App::patch('/v1/account/mfa') ->inject('requestTimestamp') ->inject('response') ->inject('user') + ->inject('session') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (bool $mfa, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) { + ->action(function (bool $mfa, ?\DateTime $requestTimestamp, Response $response, Document $user, Document $session, Database $dbForProject, Event $queueForEvents) { $user->setAttribute('mfa', $mfa); $user = $dbForProject->withRequestTimestamp($requestTimestamp, fn () => $dbForProject->updateDocument('users', $user->getId(), $user)); + if ($mfa) { + $factors = $session->getAttribute('factors', []); + $totp = TOTP::getAuthenticatorFromUser($user); + if ($totp !== null && $totp->getAttribute('verified', false)) { + $factors[] = Type::TOTP; + } + if ($user->getAttribute('email', false) && $user->getAttribute('emailVerification', false)) { + $factors[] = Type::EMAIL; + } + if ($user->getAttribute('phone', false) && $user->getAttribute('phoneVerification', false)) { + $factors[] = Type::PHONE; + } + $factors = \array_unique($factors); + + $session->setAttribute('factors', $factors); + $dbForProject->updateDocument('sessions', $session->getId(), $session); + } + $queueForEvents->setParam('userId', $user->getId()); $response->dynamic($user, Response::MODEL_ACCOUNT);