Skip to content

[Security][DX] RFC: A simple way to do programmatic logout #40663

Closed
@Seldaek

Description

@Seldaek

Description
There are various reasons why an app may need to logout a user without the user having to be redirected to the logout page, and currently there is no easy way to do this without copying some code from core which is subject to change and thus may leave one with outdated logic.

Example
Related to #40662, IMO a great API to have would be Security::programmaticLogout(Request $request)

This would figure out which firewall is relevant for the given $request, and trigger a logout event on that firewall's event dispatcher.

Why?
By digging through internals, it appears the best way to do this is the following:

        $logoutEvent = new LogoutEvent($request, $this->tokenStorage->getToken());
        $this->eventDispatcher->dispatch($logoutEvent);

        $response = $logoutEvent->getResponse();
        if (!$response instanceof Response) {
            throw new \RuntimeException('No logout listener set the Response, make sure at least the DefaultLogoutListener is registered.');
        }

        $this->tokenStorage->setToken(null);

        return $response;

This is copied from

$logoutEvent = new LogoutEvent($request, $this->tokenStorage->getToken());
$this->eventDispatcher->dispatch($logoutEvent);
$response = $logoutEvent->getResponse();
if (!$response instanceof Response) {
throw new \RuntimeException('No logout listener set the Response, make sure at least the DefaultLogoutListener is registered.');
}
$this->tokenStorage->setToken(null);
$event->setResponse($response);
I did not invent anything, but I had to find out, and now I have to copy paste this in my app to be able to call it.

On top of that, some added complexity one has to figure out is that the event dispatcher here isn't just any event dispatcher, but you have to inject the correct event dispatcher for the firewall you want to do the logout on, and so you have to define that in the service yourself.. Firewall-specific event dispatchers are mentioned in passing in the docs but it's not exactly a common concept so this is all overall not great DX, and having an easy and more visible place to do this would be nice I think.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DXDX = Developer eXperience (anything that improves the experience of using Symfony)SecurityStalled

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions