Description
Symfony version(s) affected: Observed in 4.3.3
Description
The session does not seem to be started on actions that return redirect responses. This issue comes to surface rarely because most of the time you will have loaded other pages before you visit an action that needs to both write to the session and redirect to another page.
One example is when someone might be following a link in an email (for example a reset password link or automatic login link) and the link has expired so we would need to redirect to another page and display a flash message.
The scenario above will work if you already have an active session but if you visit the site directly by the link the session isn't started and the flash messages don't get displayed. You can get around this by manually starting the session.
How to reproduce
Session does not automatically start:
<?php
namespace App\Controller\User;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
class ResetPasswordController
{
/**
* @var FlashBagInterface
*/
private $flashBag;
public function __construct(
FlashBagInterface $flashBag
) {
$this->flashBag = $flashBag;
}
public function __invoke(Request $request): Response
{
if (/* link is invalid */) {
$this->flashBag->add('danger', 'Your reset link has expired or is invalid');
return new RedirectResponse("/"); //redirects, no flash messages displayed unless session already started
}
}
}
Manually starting the session:
<?php
namespace App\Controller\User;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
class ResetPasswordController
{
/**
* @var SessionInterface
*/
private $session;
/**
* @var FlashBagInterface
*/
private $flashBag;
public function __construct(
SessionInterface $session,
FlashBagInterface $flashBag
) {
$this->session = $session;
$this->flashBag = $flashBag;
}
public function __invoke(Request $request): Response
{
$this->session->start(); //start the session manually
if (/* link is invalid */) {
$this->flashBag->add('danger', 'Your reset link has expired or is invalid');
return new RedirectResponse("/"); //works fine now with flash messages
}
}
}