phpsymfonystatelesstwo-factor-authenticationlexikjwtauthbundle

LexikJWTAuthenticationBundle subscriber event wont trigg?


is anyone comfortable with the Lexik bundle? I created a subscriber based on the AuthenticationSuccessEvent, but when I log in, it doesn’t go through my event, and I don’t understand why.

 providers:
        # used to reload user from session & other features (e.g. switch_user)
        app_user_provider:
            entity:
                class: App\Entity\User
                property: email
    firewalls:
        api:
            pattern: ^/api
            stateless: true
            entry_point: jwt
            json_login:
                check_path: /api/login # or, if you have defined a route for your login path, the route name you used
                success_handler: lexik_jwt_authentication.handler.authentication_success
                # success_handler: custom_auth_success_handler
                failure_handler: lexik_jwt_authentication.handler.authentication_failure
            jwt: ~
            refresh_jwt:
                check_path: /api/token/refresh # or, you may use the `api_refresh_token` route name
                # or if you have more than one user provider
                # provider: user_provider_name
            logout:
                path: api_token_invalidate

route.yaml :

api_login_check:
    path: /api/login

subscriber

<?php

namespace App\EventSubscriber;

use Lexik\Bundle\JWTAuthenticationBundle\Event\AuthenticationSuccessEvent;
use Lexik\Bundle\JWTAuthenticationBundle\Event\AuthenticationFailureEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class TestLexikSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            AuthenticationSuccessEvent::class => 'onAuthenticationSuccessEvent',
            AuthenticationFailureEvent::class => 'onAuthenticationFailureEvent',
        ];
    }

    public function onAuthenticationSuccessEvent(AuthenticationSuccessEvent $event): void
    {
        // Debug to check if the event is triggered
        dd($event, 'success');
    }

    public function onAuthenticationFailureEvent(AuthenticationFailureEvent $event): void
    {
        // Debug to check if the event is triggered
        dd($event, 'fail');
    }
}

I just declared a subscriber with a dd on the event that’s passed as a parameter, and nothing happens — it constantly ignores the event…

Do you have any idea why?

Thanks!

My goal is to implement Two-Factor Authentication entirely in stateless mode. The Scheb/2fa bundle only works with stateful sessions and I don't want that. I want to intercept the successful authentication and proceed with my own pipeline to set cookies on the client side, etc.


Solution

  • You have to use custom AuthenticationSuccessListener.

    namespace App\Listener;
    
    use App\Entity\User;
    use Lexik\Bundle\JWTAuthenticationBundle\Event\AuthenticationSuccessEvent;
    use Lexik\Bundle\JWTAuthenticationBundle\Events;
    use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
    
    #[AsEventListener(event: Events::AUTHENTICATION_SUCCESS)]
    class AuthenticationSuccessListener
    {
        public function __invoke(AuthenticationSuccessEvent $event): void
        {
            $data = $event->getData();
            $user = $event->getUser();
    
            if (!$user instanceof User) {
                return;
            }
    
            $event->setData($data);
        }
    }