05 March 2020

Symfony 4: Using the JSON Login system with Symfony's Remember Me service

As with all topics related to software development, there is always more than one solution to a problem. The following proposition is simply one possible solution and not intended to be definitive.


  • Configure the security firewall with a JSON login and Remember Me listener
  • Create a public Alias for the Symfony's private Remember Me Service
  • Add a Login Controller Method for creating the Remember Me Cookie


If you're building a Restful API using Symfony 4, conventional wisdom suggests that JSON Web Tokens (JWT) should be your go to solution for authenticating clients... However, in this fancy, modern world of Single Page Applications (SPAs), JavaScript frameworks (Angular, React, Vue, et al) and jQuery, quite often you'll have a website or blog, with membership services, that will have integrated numerous asynchronous transactions between the client and server.

The standard Symfony Form Login system includes a simple and reliable system for allowing members to authenticate and remain logged in beyond the expiry of the PHP session. Unfortunately, but for valid reasons, Symfony's JSON Login doesn't provide this feature. Making it work isn't difficult - Once you know how...

Firstly, ensure you set-up your configuration files so that you're security firewall has the remember me available. You will have to include the "form_login" section otherwise you'll get the following exception:

You must configure at least one remember-me aware listener (such as form-login)
for each firewall that has remember-me enabled.

You can always go and configure a remember me aware listener (the "elite" thing to do), but you can also avoid this, and save development time, by adding two lines to the "security.yaml" config.

# config/packages/security.yaml
    # ...
        # ...	
                secret: '%kernel.secret%'
                lifetime: 604800 # in seconds
                path: /
                always_remember_me: false
                remember_me: true
                check_path: api_auth_login

                remember_me: true

You will also need to create a public alias for the remember me service so that you can use that within your own Application's Controllers:

# config/services.yaml
    # ...	
        # ...	
            alias: security.authentication.rememberme.services.simplehash.main
            public: true

As a final step, you need to complete the Remember Me process inside your own Login method within your App's Authentication Controller:

# src/Controller/AuthController.php

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;

use App\Entity\MyUserEntity;

class AuthController extends AbstractController
  * @Route("/api/auth/login", name="api_auth_login", methods={"POST"})
  public function login(Request $request)
    $user = $this->getUser();
    if( $user instanceof MyUserEntity ){

      // Create a response object so we can attach the Rememeber Me cookie
      // to be sent back to the client
      $response = new JsonResponse( [
        'username' => $user->getUsername(),
        'roles' => $user->getRoles()
        ... code
      ] );

      // Capture the JSON Payload posted from the client
      $payload = [];
      if( $request->getContentType() === 'json' ) {
        $payload = json_decode($request->getContent(), true);
        if (json_last_error() !== JSON_ERROR_NONE) {
          throw new \Exception('Invalid json: ' . json_last_error_msg() );

      // Look for the "_remember_me" form field and cast it to a Boolean
      $rememeberMe = isset($payload['_remember_me']) 
        ? filter_var( $payload['_remember_me'], FILTER_VALIDATE_BOOLEAN )
        : false;
      // Set the remember me token
      if( $rememeberMe ){
        $securityToken = $this->container->get('security.token_storage')->getToken();
// Access the service using the Alias created in the services.yaml config $rememberMeService = $this->container->get('app.authentication.rememberme.services.simplehash'); $rememberMeService->loginSuccess( $request, $response, $securityToken ); } return $response; } new JsonResponse( [ 'message' => 'Login failed' ]); } ... code }

As one small, additional example, on the client-side, you'll probably do something like this:

# Angular Service
  public login(username: string, password: string, rememberMe: boolean): Observable<User> {
    return this.http.post<User>(`https://www.domain.com.au/auth/login`, {
      username: username,
      password: password,
      _remember_me: rememberMe

# jQuery AJAX
  var login = function( username, password, rememberMe ){
    return $.ajax({
        type: 'POST',
        contentType: 'application/json',
        url: 'https://www.domain.com.au/auth/login',
        data: JSON.stringify( {
            username: username,
            password: password,
            _remember_me: rememberMe
        } )


PurcellYoon are a team of expert Symfony Developers with a passion for creating exceptional digital experiences. We are committed to delivering superior Symfony Applications for all our partners and clients.

We'd love to talk with you about Symfony Development.
More questions? Get in touch.