I am just upgrading my symfony 4.4 application to 5.3 to use some new cool stuff (UX, UUID, ..). So I started a new project and ran the make:auth
command to create the security components at latest defaults. Everything works perfect, except the remember me functionality. The cookie is just not set (regardless which browser). Maybe you can help me
security.yaml
security:
enable_authenticator_manager: true
password_hashers:
App\Entity\User:
algorithm: auto
providers:
app_user_provider:
entity:
class: App\Entity\User
property: email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
lazy: true
provider: app_user_provider
custom_authenticator: App\Security\LoginFormAuthenticator
pattern: ^/
logout:
path: _logout
target: _index
remember_me:
secret: '%env(APP_SECRET)%'
lifetime: 31536000 # 1 year in seconds
always_remember_me: true
path: _index
switch_user: true
role_hierarchy:
ROLE_USER: ROLE_USER
ROLE_ADMIN: [ROLE_USER, ROLE_ALLOWED_TO_SWITCH]
access_control:
- { path: ^/login, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/reset-password, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/datenschutz, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/impressum, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/worker, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
- { path: ^/, role: ROLE_USER }
LoginFormAuthenticator
<?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\Core\Security;
use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
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\Authenticator\Passport\PassportInterface;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
class LoginFormAuthenticator extends AbstractLoginFormAuthenticator
{
use TargetPathTrait;
public const LOGIN_ROUTE = '_login';
private UrlGeneratorInterface $urlGenerator;
public function __construct(UrlGeneratorInterface $urlGenerator)
{
$this->urlGenerator = $urlGenerator;
}
public function authenticate(Request $request): PassportInterface
{
$email = $request->request->get('email', '');
$request->getSession()->set(Security::LAST_USERNAME, $email);
return new Passport(
new UserBadge($email),
new PasswordCredentials($request->request->get('password', '')),
[
new CsrfTokenBadge('authenticate', $request->get('_csrf_token')),
]
);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) {
return new RedirectResponse($targetPath);
}
return new RedirectResponse($this->urlGenerator->generate('_index'));
}
protected function getLoginUrl(Request $request): string
{
return $this->urlGenerator->generate(self::LOGIN_ROUTE);
}
public function supportsRememberMe(): bool
{
return true;
}
}
login.html.twig
{% extends 'base.html.twig' %}
{% block title %}{{ ('meta.title.login')|trans }}{% endblock %}
{% block body %}
<h1>{{ ('security.login.header')|trans }}</h1>
<form method="post">
{% if error %}
<div class="alert alert-danger">{{ error.messageKey|trans(error.messageData, 'security') }}</div>
{% endif %}
<div class="mb-3">
<label for="inputEmail" class="form-label">{{ ('security.login.email')|trans }}</label>
<input type="email" value="{{ last_username }}" name="email" id="inputEmail" class="form-control" autocomplete="email" required autofocus>
</div>
<div class="mb-3">
<label for="inputPassword" class="form-label">{{ ('security.login.password')|trans }}</label>
<input type="password" name="password" id="inputPassword" class="form-control" autocomplete="current-password" required>
</div>
<div class="mb-3">
<a href="{{ path('app_forgot_password_request') }}">
{{ ('button.forgot_password')|trans }}
</a>
</div>
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">
<button class="btn btn-lg btn-outline-success" type="submit">
{{ ('security.login.button')|trans }}
</button>
</form>
{% endblock %}
Thanks a lot in advance!!
--------------- EDIT ----------------------
I originally asked this question for version 5.4, but is relevant for 5.3 as well - I tried both without getting the cookie to be set
path
not be the actual path and not the name of the path? – Avalanche