I created a website with a user login using Sulu CMF. For the user login, I would like to create a "remember me" checkbox. According to Symfony docs, all that need to be done is
security.yaml
name="_remember_me"
The first two points are straight forward. For the third point, "add Remember Me Support to the Authenticator" I am a bit lost, as with sulu I am not using a custom authenticator, but Sulu rather provides the authentication mechanism, with Sulu users and roles an all that.
How can I tell the Sulu authenticator to add the RememberMeBadge
to the authentication Passport
as described in the docs?
Update: When loggin in, the server responds with the REMEMBERME cookie, but with the value "deleted".
Finally I got it working by creating a custom Authenticator.
The reason why it did not work in the first place is due to the symfony FormLoginAuthenticator
that creates the RememberMeBadge
, but does not enable it. See https://github.com/symfony/security-http/blob/7.0/Authenticator/FormLoginAuthenticator.php
Here you see that the RememberMeBadge is disabled by default: https://github.com/symfony/security-http/blob/7.0/Authenticator/Passport/Badge/RememberMeBadge.php
That fact that the badge is created but not enabled, does not make sense to me, maybe this is a bug in the Symfony framework.
However, a custom Authenticator that creates and enables the badge, solved the issue for me.
<?php
namespace App\Security;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Http\SecurityRequestAttributes;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
class CustomAuthenticator extends AbstractLoginFormAuthenticator
{
use TargetPathTrait;
public const LOGIN_ROUTE = 'app_login';
public function __construct(private UrlGeneratorInterface $urlGenerator)
{
}
public function authenticate(Request $request): Passport
{
$username = $request->request->get('_username', '');
$request->getSession()->set(SecurityRequestAttributes::LAST_USERNAME, $username);
return new Passport(
new UserBadge($username),
new PasswordCredentials($request->request->get('_password', '')),
[
new CsrfTokenBadge('authenticate', $request->request->get('_csrf_token')),
(new RememberMeBadge())->enable(),
]
);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) {
return new RedirectResponse($targetPath);
}
// redirect to homepage
return new RedirectResponse('/');
}
protected function getLoginUrl(Request $request): string
{
return $this->urlGenerator->generate(self::LOGIN_ROUTE);
}
}
The authenticator was created using the symfony cli command php bin/console make:auth
with some minor adjustments.