From 732840b7228ea641e1bd74246228e99a29553c4d Mon Sep 17 00:00:00 2001 From: Dimitri Sitchet Tomkeu Date: Wed, 9 Sep 2026 21:05:22 +0100 Subject: [PATCH] fix(auth) : exiger des actions de connexion pour les liens magiques MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Lancer les actions de connexion configurées lors de la vérification des liens magiques - Conserver la notification "magicLogin" jusqu'à ce que les actions en attente soient terminées --- src/Authentication/Authenticators/Session.php | 41 +++++++++++++++++-- src/Controllers/MagicLinkController.php | 18 +++++--- 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/src/Authentication/Authenticators/Session.php b/src/Authentication/Authenticators/Session.php index 86b4a5b..af660bb 100644 --- a/src/Authentication/Authenticators/Session.php +++ b/src/Authentication/Authenticators/Session.php @@ -53,6 +53,10 @@ class Session extends BaseAuthenticator implements AuthenticatorInterface private const STATE_PENDING = 2; // 2FA ou activation requise. private const STATE_LOGGED_IN = 3; + // Marqueurs de session pour la connexion sans mot de passe + private const MAGIC_LOGIN_TEMP_DATA = 'magicLogin'; + private const PENDING_LOGIN_METHOD = 'auth_action_login_method'; + /** * L'état d'authentification de l'utilisateur */ @@ -127,7 +131,7 @@ public function attempt(array $credentials): Result // Déclenchez un événement en cas d'échec afin que les développeurs aient la possibilité de leur faire savoir que quelqu'un a tenté de se connecter à leur compte unset($credentials['password']); - service('event')->emit('schild:failedLogin', $credentials); + service('event')->emit('schild:failedLogin', argv: $credentials); return $result; } @@ -177,7 +181,7 @@ public function attempt(array $credentials): Result */ public function startUpAction(string $type, User $user): bool { - if ('' === $actionClass = config('auth.actions.' . $type) ?? '') { + if ('' === $actionClass = parametre('auth.actions.' . $type) ?? '') { return false; } @@ -249,6 +253,34 @@ public function completeLogin(User $user): void // une connexion réussie service('event')->emit('schild:login', $user); + + // Termine la notification de connexion sans mot de passe après toute tentative de connexion en attente. + $this->completePendingLoginMethod(); + } + + /** + * Indique que l'action de connexion en cours provient d'une méthode de connexion sans mot de passe. + */ + public function setPendingLoginMethod(string $method): void + { + $this->setSessionUserKey(self::PENDING_LOGIN_METHOD, $method); + } + + private function completePendingLoginMethod(): void + { + $method = $this->getSessionUserKey(self::PENDING_LOGIN_METHOD); + + if ($method === null) { + return; + } + + $this->removeSessionUserKey(self::PENDING_LOGIN_METHOD); + + if ($method === self::ID_TYPE_MAGIC_LINK) { + session()->setTempdata(self::MAGIC_LOGIN_TEMP_DATA, true); + + service('event')->emit('schild:magicLogin'); + } } /** @@ -765,7 +797,7 @@ private function issueRememberMeToken(): void // Réinitialisez pour ne pas gâcher les futurs appels. $this->shouldRemember = false; - } elseif ($this->getRememberMeToken()) { + } elseif ($this->getRememberMeToken() !== null) { $this->removeRememberCookie(); // @TODO supprimer l'enregistrement de jeton. @@ -893,6 +925,9 @@ private function calcExpires(): Date return Date::now()->addSeconds($rememberLength); } + /** + * @param non-empty-string $rawToken + */ private function setRememberMeCookie(string $rawToken): void { // Créer le cookie diff --git a/src/Controllers/MagicLinkController.php b/src/Controllers/MagicLinkController.php index fff9625..edde4a3 100644 --- a/src/Controllers/MagicLinkController.php +++ b/src/Controllers/MagicLinkController.php @@ -16,6 +16,7 @@ use BlitzPHP\Exceptions\PageNotFoundException; use BlitzPHP\Http\Redirection; use BlitzPHP\Schild\Authentication\Authenticators\Session; +use BlitzPHP\Schild\Entities\User; use BlitzPHP\Schild\Models\LoginModel; use BlitzPHP\Schild\Models\UserIdentityModel; use BlitzPHP\Schild\Models\UserModel; @@ -187,6 +188,18 @@ public function verify(): Redirection return redirect()->route('auth-action-show')->withErrors(lang('Auth.needActivate')); } + $user = $this->provider->findById($identity->user_id); + + // Lancer toute action de connexion qui a été définie. + if ($user instanceof User && $authenticator->startUpAction('login', $user) && $authenticator->hasAction($user->id)) { + $this->recordLoginAttempt($identifier, true, $user->id); + $authenticator->setPendingLoginMethod(Session::ID_TYPE_MAGIC_LINK); + + return redirect()->route('auth-action-show'); + } + + $authenticator->setPendingLoginMethod(Session::ID_TYPE_MAGIC_LINK); + // Connecter l'utilisateur $authenticator->loginById($identity->user_id); @@ -194,11 +207,6 @@ public function verify(): Redirection $this->recordLoginAttempt($identifier, true, $user->id); - // Donnez au développeur un moyen de connaître l'utilisateur connecté via un lien magique. - session()->setTempdata('magicLogin', true); - - $this->event->emit('schild:magicLogin'); - // Obtenez notre URL de redirection de connexion return redirect()->to(($this->config->loginRedirect)()); }