markitosgv/JWTRefreshTokenBundle

Add data as payload to the refresh route

fhuszti opened this issue · 2 comments

As per the title, is there any way to add data to the response of the refresh route (/token/refresh)?
The RefreshEvent doesn't have any data associated to it so hooking up to this event isn't useful for that.

My use case is, I'm returning basic user data with the login response from lexik, added thanks to their AuthenticationSuccessEvent. This is basically my session data to populate the header and such on my FE. I would like to return the same data whenever I refresh my token.

For now my solution is to create a route to get this basic data but it's cumbersome having to call the refresh route and then this data route at every refresh, instead of getting it all in one go.

That same AuthenticationSuccessEvent

With the refresh_jwt authenticator, the default success handler just uses the Lexik bundle's success handler so everything after the RefreshEvent is basically re-using that same part of the code (that's how the refresh token gets appended to the response, too). Off the top of my head, I don't quite remember the flow for the older authentication code, but if you're on Symfony 5.4 or later I'd say make sure that authenticator is in use and you should be good to go.

Thanks for answering!
The issue wasn't with the authenticator but you helped me debug it. I'm leaving this if anyone has the problem some day:

I'm on Symfony 7 currently. This is my firewall config:

firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    login:
        pattern: ^/api/login
        stateless: true
        provider: custom_user_provider
        json_login:
            check_path: /api/login_check
            success_handler: lexik_jwt_authentication.handler.authentication_success
            failure_handler: lexik_jwt_authentication.handler.authentication_failure
    api:
        pattern: ^/api
        stateless: true
        provider: jwt
        entry_point: jwt
        jwt:
            authenticator: app.custom_authenticator
        refresh_jwt:
            check_path: /api/token/refresh
        logout:
            path: api_token_invalidate

As @mbabker said, the AuthenticationSuccessEvent is indeed used. Problem was, I had this in my listener:

public function __invoke(AuthenticationSuccessEvent $event): void
{
    $data = $event->getData();
    $user = $event->getUser();

    if (!$user instanceof SymfonyUserAdapter) {
        return;
    }
    $domainUser = $user->getDomainUser();

    $data['user'] = [
        'id' => $domainUser->getId(),
        'username' => $domainUser->getUsername()->getValue(),
        'email' => $domainUser->getEmail()->getValue(),
        'role' => $domainUser->getRole()->value
    ];

    $event->setData($data);
}

As I didn't indicate which provider I wanted to use in my api.refresh_jwt firewall config, when refreshing the token it used by default the current firewall provider, so the jwt one. Which was not an instance of SymfonyUserAdapter, because I'm using the lexik config of not fetching from database everytime.
I just had to explicitely set provider: custom_user_provider under api.refresh_jwt. Fairly simple in the end.

Thanks!