Symfony 8.2 Nouveauté Publié le

Se déconnecter par un bouton, et non plus par un lien

logout_button() affiche un formulaire de déconnexion en POST, jeton CSRF compris : un lien suivi par un robot ne déconnecte plus personne.

Notions abordées : SécuritéCSRFTwig

Nouveau dans Symfony 8.2 (en développement). Se déconnecter en suivant un lien, c'est se déconnecter sur un GET. Or un GET part sans qu'on le demande : un navigateur qui précharge les liens de la page, une extension, un robot qui explore le site. Et n'importe quel site peut envoyer son visiteur sur /deconnexion : les cookies suivent la navigation, et le voilà déconnecté.

Une déconnexion en POST

On limite la route de déconnexion à POST, et le pare-feu vérifie un jeton CSRF (enable_csrf: true sous logout). Symfony 8.2 ajoute de quoi afficher le formulaire qui va avec :

{{ logout_button() }} {# sans libellé, le bouton dit « Log out », non traduit #}

{# un libellé, un pare-feu, des attributs pour le bouton et pour le formulaire #}
{{ logout_button('Se déconnecter', attr: { class: 'btn-link' }, form_attr: { class: 'd-inline' }) }}

logout_form() donne l'action et les champs cachés (le jeton compris), pour écrire le formulaire soi-même :

{% set deconnexion = logout_form() %}
<form method="post" action="{{ deconnexion.action }}">
    {% for nom, valeur in deconnexion.fields %}
        <input type="hidden" name="{{ nom }}" value="{{ valeur }}">
    {% endfor %}
    <button>Se déconnecter</button>
</form>

L'usurpation d'identité a les siens : impersonation_button() et impersonation_exit_button().

Autre nouveauté : target: ~ sous logout supprime la redirection après la déconnexion, et laisse le contrôleur de la route répondre, par exemple en JSON pour une API.

À faire

La page du compte propose un lien « Se déconnecter » (connectez-vous avec ada / lovelace dans l'aperçu). Remplacez-le par un bouton « Se déconnecter » : la déconnexion n'accepte plus que POST, avec un jeton CSRF.

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