Home > OS >  Symfony custom logout
Symfony custom logout

Time:01-18

I am trying to create a logout feature which when clicked from the below (example) redirects to the necessary page.

Example:

  1. If anybody clicks logout with website beginning with aaa.io/user -> go to aaa.io/login.
  2. If anybody clicks logout with website beginning with aaa.io/dev/{id} -> go to aaa.io/home/{id}

How to create two logout feature which will redirect to two seperate pages? I have tried with first example and works fine.I heard we can do it using Symfony firewall but unable to get it.

#security.yaml
security:
    enable_authenticator_manager: true
    # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
    password_hashers:
        Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
        App\Entity\Dimitry:
            algorithm: auto

    providers:
        app_user_provider:
            entity:
                class: App\Entity\Dimitry
                property: email
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            lazy: true
            provider: app_user_provider
            custom_authenticator: App\Security\LoginAuthenticator
            logout:
                path: app_logout
                target: app_login

//Security Controller
#[Route(path: '/login', name: 'app_login')]
    public function login(AuthenticationUtils $authenticationUtils): Response
    {
         if ($this->getUser()) {
             return $this->redirectToRoute('app_home');
         }

        // get the login error if there is one
        $error = $authenticationUtils->getLastAuthenticationError();
        // last username entered by the user
        $lastUsername = $authenticationUtils->getLastUsername();

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

    #[Route(path: '/logout', name: 'app_logout')]
    public function logout()
    {
        return $this->redirectToRoute('app_login');

        //throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
    }

CodePudding user response:

The logout method is never called because it's intercepted by the logout key on your firewall. So the code lines in the public function logout won't be executed.

IMO, you could use events :

  1. Create a subscriber,
  2. Subscribe on LogoutEvent::class,
  3. Analyze the request provided by the logout event
  4. Use it to determine the route,
  5. Catch the response provided by the logout event,
  6. Use the UrlGenerator to redirect user,
  7. Update the response to redirect to the corresponding route

Documentation provides a very good example, you can use as a template for your logic. Your subscriber could be like this one:

// src/EventListener/LogoutSubscriber.php
namespace App\EventListener;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Http\Event\LogoutEvent;

class LogoutSubscriber implements EventSubscriberInterface
{
    public function __construct(
        private UrlGeneratorInterface $urlGenerator
    ) {
    }

    public static function getSubscribedEvents(): array
    {
        //2 - Subscribe to LogoutEvent
        return [LogoutEvent::class => 'onLogout'];
    }

    public function onLogout(LogoutEvent $event): void
    {
        // get the security token of the session that is about to be logged out
        $token = $event->getToken();

        // 3. get the current request
        $request = $event->getRequest();

        // 4. Your own logic to analyze the URL
        $route = 'homepage';//default route
        if (...) {
            $route = 'URL1';
        }
        if (...) {
            $route = 'URL2';
        }

        // 5. get the current response, if it is already set by another listener
        $response = $event->getResponse();

        // configure a custom logout response to the homepage
        $response = new RedirectResponse(
            $this->urlGenerator->generate($route),
            RedirectResponse::HTTP_SEE_OTHER
        );
        $event->setResponse($response);
    }
}
  • Related