Symfony 8.2 Nouveauté Publié le

Un lien de connexion qui garde sa destination

createLoginLink() signe désormais ses paramètres : le return_to d'un lien de connexion ne se retouche plus.

Notions abordées : Security

Nouveau dans Symfony 8.2 (en développement). Un lien de connexion (login_link) connecte sans mot de passe : il porte l'identifiant, une date d'expiration et une signature. Tout ce qu'on y ajoutait ensuite — la page où ramener le lecteur, typiquement — restait hors signature. N'importe qui pouvait donc le changer, et faire d'un vrai lien, envoyé par vous, une redirection vers un autre site.

Des paramètres signés

createLoginLink() accepte désormais des paramètres, que la signature couvre :

$lien = $liens->createLoginLink($utilisateur, $request, null, ['return_to' => '/compte/factures']);

Changez ou retirez l'un d'eux, et le lien ne connecte plus personne. À l'arrivée, les paramètres vérifiés attendent dans un attribut de la requête :

$retour = $request->attributes->get('_login_link_parameters')['return_to'] ?? null;

Lisez-les là, pas dans la query string : un paramètre ajouté après coup — un traceur de messagerie, ou pire — y apparaît sans avoir été signé. Symfony l'ignore ; votre code doit en faire autant.

La signature prouve que return_to vient de vous, pas qu'il mène chez vous : quiconque peut demander un lien peut aussi demander un lien signé vers un autre site. N'y acceptez donc qu'un chemin du site.

À faire

LienController fabrique le lien qui partirait par mail (la réponse le montre) et y colle return_to à la main ; RedirectionApresLien le relit dans la query string. Le lien est authentique, sa destination non : remplacez /compte/factures par un autre site, et le lecteur s'y retrouve, connecté.

  1. Faites signer return_to par le lien.
  2. Dans RedirectionApresLien, ne lisez plus que les paramètres signés.
  3. N'y suivez qu'un chemin du site (/…, mais pas //…) ; sinon, menez à /compte.

D'où vient la fonctionnalité : la pull request d'origine.