Search code examples
phpsymfonysymfony5symfony-security

Auto remember-me after register


I'm using Symfony 5.2 / PHP8

My login form is simply email + password I do an auto "remember me" using

    firewalls:
        endusers:
            ...
            remember_me:
                secret: '%kernel.secret'
                lifetime: 604800 # 1 week in seconds
                path: /
                always_remember_me: true

this works without any issue

The problem is during registration, I autologin the user using this snippet

            $token = new UsernamePasswordToken(
                user: $user,
                credentials: null,
                firewallName: 'endusers',
                roles: $user->getRoles(),
            );
            $this->container->get('security.token_storage')->setToken($token);
            $this->container->get('session')->set('_security_endusers', serialize($token))

and while this work, it unfortunately does not trigger the remember me feature (which is normal to my understanding, as the remember me is trigger normally one level higher by the 'onloginsuccess' event which is not triggered here)

So I would like to know how to have also the remember me set up in the case above


Solution

  • Update Symfony 5.3

    There's now a RememberMeHandlerInterface service that works with autowiring, so you simply need to inject it and use it like this

                $rememberMe->createRememberMeCookie($user);
    

    no need to update your services.yaml

    Symfony 5.2

    You can create the remember_me cookie by using RememberMeServicesInterface and calling loginSuccess. There's no autowiring service for it, though, so you have to create an alias in order to inject it in your controller.

    The container alias for the service is security.authentication.rememberme.services.simplehash.<firewall_name>. Depending on the configuration it could be other than simplehash, you can verify it by executing bin/console debug:container rememberme.services.

    Once you've verified the registered service, create the alias in config/services.yaml:

    services:
         # ...
         Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface:
             alias: security.authentication.rememberme.services.simplehash.endusers
    

    Now you can inject the service in your controller and call the function after successful registration.

    public function register(Request $request, RememberMeServicesInterface $rememberme, /* Other deps */)
    {
        $token = new UsernamePasswordToken($user, null, 'endusers', $user->getRoles());
            
        $this->container->get('security.token_storage')->setToken($token);
        $this->container->get('session')->set('_security_endusers', serialize($token));
        
        // RememberMe needs a Response object so cookies can be set in the output
        $response = $this->redirectToRoute($route);
        
        $rememberme->loginSuccess($request, $response, $token);
        
        return $response;
    }
    

    According to your firewall configuration, always_remember_me is enabled, but in case it weren't, you'd need to set the remember_me_parameter (_remember_me by default) in the request for the service to actually create the cookie.

    $request->attributes->add(['_remember_me' => true]);
    $rememberme->loginSuccess(/*...*/);