LexikJWTAuthenticationBundle: Cannot extend JWTAuthenticator and override loadUser method

Hi there!

I use this bundle in my symfony 6 project to authenticate my users by jwt token. Everything is going fine until I want to create a custom authenticator to add some logic in how I authenticate my users. After following the documentation https://github.com/lexik/LexikJWTAuthenticationBundle/blob/2.x/Resources/doc/6-extending-jwt-authenticator.rst, my authenticator is never called and I don’t have any error either.

In my services.yaml file

# config/services.yaml
services:
      app.jwt_custom_api_authenticator:
           class: App\Http\Api\Security\Authenticator\JWTCustomApiAuthenticator
           parent: lexik_jwt_authentication.security.jwt_authenticator

In security.yaml file

# config/packages/security.yaml
security:
  enable_authenticator_manager: true
  password_hashers:
    Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
    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

    login:
      pattern: ^/api/auth
      stateless: true
      json_login:
        username_path: email
        check_path: api_login_check
        success_handler: lexik_jwt_authentication.handler.authentication_success
        failure_handler: lexik_jwt_authentication.handler.authentication_failure


      refresh_jwt:
        check_path: api_refresh_token
        provider: app_user_provider

    api:
      pattern: ^/api
      stateless: true
      jwt:
        authenticator: app.jwt_custom_api_authenticator

    main:
      lazy: true
      provider: app_user_provider


In my App\Http\Api\Security\Authenticator\JWTCustomApiAuthenticator file

<?php

namespace App\Http\Api\Security\Authenticator;

use App\Entity\User;
use Lexik\Bundle\JWTAuthenticationBundle\Security\Authenticator\JWTAuthenticator;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface;

class JWTCustomApiAuthenticator extends JWTAuthenticator
{
  protected function loadUser(array $payload, string $identity): UserInterface
  {
    /** @var UserInterface|User $user */
    $user  = parent::loadUser($payload, $identity);
    if ($user->isBlocked()){
      $ex = new UserNotFoundException('Your account has been deactivated by the administrators');
      $ex->setUserIdentifier($identity);
      throw $ex;
    }
    return $user;
  }
}

SYMFONY 6 + PHP 8.1

I would like to know how to implement my authenticator logic.

About this issue

Most upvoted comments

I also searched in vain how it proceeds to authenticate the default user just in api/login_check in the routes.yaml file We are almost in the same need because I too don’t want to generate the token if the user’s account is locked, and the only way to do it and during the user retrieval in the loadUser method, unlike you who are looking to generate the token either by the email address or by the username.

Have you thought about user checker? How about give it a try? https://symfony.com/doc/current/security/user_checkers.html

It’s work for me fine and the jwt is not generated. I think this is the best solution to do this instead of to override the JWTAuthenticator laodUser method.

In security.yaml

firewalls:
  dev:
    pattern: ^/(_(profiler|wdt)|css|images|js)/
    security: false

  login:
    ...
    user_checker: App\Http\Api\Security\Checker\JWTUserChecker
    json_login:
      username_path: email
      check_path: api_login_check
      success_handler: lexik_jwt_authentication.handler.authentication_success
      failure_handler: lexik_jwt_authentication.handler.authentication_failure