Search code examples
symfonysecuritylogout

[Symfony 5]Confirmation message after logout


On Symfony 5, using the built-in login system, it seems impossible to add a confirmation message after logout. I have followed strictly the steps described on the official website. Unfortunately, the method logout inside the SecurityController is useless. I'm redirected directly on the login page.

Here you will have my security.yaml file :

security:
encoders:
    App\Entity\User:
        algorithm: auto


# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
    # used to reload user from session & other features (e.g. switch_user)
    app_user_provider:
        entity:
            class: App\Entity\User
            property: email
    # used to reload user from session & other features (e.g. switch_user)
firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    main:
        anonymous: lazy
        provider: app_user_provider
        guard:
            authenticators:
                - App\Security\LoginFormAuthenticator
        logout:
            path: logout
            target: login

        remember_me:
            secret:   '%kernel.secret%'
            lifetime: 604800 # 1 week in seconds
            path:     home
            always_remember_me: true

        # activate different ways to authenticate
        # https://symfony.com/doc/current/security.html#firewalls-authentication

        # https://symfony.com/doc/current/security/impersonating_user.html
        # switch_user: true

# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
    - { path: ^/logout$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/, roles: IS_AUTHENTICATED_FULLY }
    - { path: ^/admin, roles: [IS_AUTHENTICATED_FULLY, ROLE_ADMIN] }
    - { path: ^/profile, roles: [IS_AUTHENTICATED_FULLY, ROLE_USER] }

And the Controller :

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;

class SecurityController extends AbstractController
{
    public function login(AuthenticationUtils $authenticationUtils): Response
    {
        if ($this->getUser()) {
            return $this->redirectToRoute('home');
        }

        // get the login error if there is one
        $error = $authenticationUtils->getLastAuthenticationError();

        return $this->render('security/login.html.twig', ['last_username' => null, 'error' => $error]);
    }

    public function logout()
    {
        throw new \Exception('Don\'t forget to activate logout in security.yaml');
    }
}

?>

Thank you for your help !


Solution

  • For anyone who's wondering how exactly they can implement the external redirect with the new logout customization:

    As stated in the documentation, create a new CustomLogoutListener class and add it to your services.yml configuration.

    The CustomLogoutListener class should implement the onSymfonyComponentSecurityHttpEventLogoutEvent method, which will receive the LogoutEvent as a parameter, that will allow you to set the response:

    namespace App\EventListener;
    
    use JetBrains\PhpStorm\NoReturn;
    use Symfony\Component\HttpFoundation\RedirectResponse;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\Security\Http\Event\LogoutEvent;
    
    class CustomLogoutListener
    {
        /**
         * @param LogoutEvent $logoutEvent
         * @return void
         */
        #[NoReturn]
        public function onSymfonyComponentSecurityHttpEventLogoutEvent(LogoutEvent $logoutEvent): void
        {
            $logoutEvent->setResponse(new RedirectResponse('https://where-you-want-to-redirect.com', Response::HTTP_MOVED_PERMANENTLY));
        }
    }
    
    
    # config/services.yaml
    services:
        # ...
        App\EventListener\CustomLogoutListener:
            tags:
                - name: 'kernel.event_listener'
                  event: 'Symfony\Component\Security\Http\Event\LogoutEvent'
                  dispatcher: security.event_dispatcher.main