Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions src/Jmikola/AutoLogin/Http/Firewall/AutoLoginListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\Firewall\ListenerInterface;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;

class AutoLoginListener implements ListenerInterface
{
Expand All @@ -26,6 +28,8 @@ class AutoLoginListener implements ListenerInterface
private $securityContext;
private $tokenParam;
private $options;
private $successHandler;
private $rememberMeServices;

/**
* Constructor.
Expand All @@ -38,7 +42,7 @@ class AutoLoginListener implements ListenerInterface
* @param EventDispatcherInterface $dispatcher
* @param array $options
*/
public function __construct($securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, $tokenParam, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, array $options = array())
public function __construct($securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, $tokenParam, AuthenticationSuccessHandlerInterface $successHandler, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, array $options = array())
{
if (!($securityContext instanceof SecurityContextInterface) &&
!($securityContext instanceof TokenStorageInterface)) {
Expand All @@ -53,6 +57,7 @@ public function __construct($securityContext, AuthenticationManagerInterface $au
$this->authenticationManager = $authenticationManager;
$this->providerKey = $providerKey;
$this->tokenParam = $tokenParam;
$this->successHandler = $successHandler;
$this->logger = $logger;
$this->dispatcher = $dispatcher;

Expand All @@ -61,12 +66,22 @@ public function __construct($securityContext, AuthenticationManagerInterface $au
), $options);
}

/**
* Sets the RememberMeServices implementation to use.
*
* @param RememberMeServicesInterface $rememberMeServices
*/
public function setRememberMeServices(RememberMeServicesInterface $rememberMeServices)
{
$this->rememberMeServices = $rememberMeServices;
}

/**
* @see Symfony\Component\Security\Http\Firewall\ListenerInterface::handle()
*/
public function handle(GetResponseEvent $event)
public function handle(GetResponseEvent $requestEvent)
{
$request = $event->getRequest();
$request = $requestEvent->getRequest();

if ( ! ($this->isTokenInRequest($request))) {
return;
Expand Down Expand Up @@ -106,6 +121,14 @@ public function handle(GetResponseEvent $event)
if ($authenticatedToken = $this->authenticationManager->authenticate($token)) {
$this->securityContext->setToken($authenticatedToken);

//return response to redirect after successful login
$response = $this->successHandler->onAuthenticationSuccess($request, $authenticatedToken);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the AuthenticationSuccessHandlerInterface mainly used for creating redirect responses? I don't recall using these before, but I'd be curious to see other listeners (either in Symfony or outside) that use this service if you have prior art to link to.

It's been a while, but I believe this component purposefully avoids setting a response object or otherwise getting in the way of the request.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just took this code from Symfony\Component\Security\Http\Firewall\AbstractAuthenticationListener::onSuccess because it was used by symfony's default authentication routine I was stepping through in debugger. By doing this I achieved correct redirect after successful login, which I think is good for security reasons because it is really easy to expose you login details by just coping and then sending that link to colleague. It was necessary to generate a proper response to make remeber_me cookie work.

$requestEvent->setResponse($response);
if (null !== $this->rememberMeServices) {
//set remember me cookies
$this->rememberMeServices->loginSuccess($request, $response, $authenticatedToken);
}

if (null !== $this->dispatcher) {
$event = new InteractiveLoginEvent($request, $authenticatedToken);
$this->dispatcher->dispatch(SecurityEvents::INTERACTIVE_LOGIN, $event);
Expand Down