Nuryagdy Mustapayev
Nuryagdy Mustapayev

Reputation: 775

JWT Authentication in Symfony 4.3 with Guard

I am new to symfony.

I am trying to implement JWT authentication using lexik/jwt-authentication-bundle v2.6 and Symfony v4.3 I implemented login successfully, it provides me with jwt token. And accessing restricted areas with JWT token also working with following configuration in security.yml

login:
            pattern: ^/login
            stateless: true
            anonymous: true
            json_login:
                check_path: /login_check
                success_handler: lexik_jwt_authentication.handler.authentication_success
                failure_handler: lexik_jwt_authentication.handler.authentication_failure
api:
            pattern: ^/
            stateless: true
            guard:
                authenticators:
                    - lexik_jwt_authentication.jwt_token_authenticator

But this configuration giving following warning: @deprecated since 2.0, use the "lexik_jwt_authentication.jwt_token_authenticator" Guard

So I implemented my own App\Security\TokenAuthenticator which extends AbstractGuardAuthenticator and changed

guard:
            authenticators:
                - lexik_jwt_authentication.jwt_token_authenticator

to

guard:
            authenticators:
                #- lexik_jwt_authentication.jwt_token_authenticator
                - App\Security\TokenAuthenticator

After changing configuration I am getting "Invalid JWT Token" error. Error is thrown because in vendor/lexik/jwt-authentication-bundle/Services/JWTManager.php (line 96)

    /**
 * {@inheritdoc}
 */
public function decode(TokenInterface $token)
{
    if (!($payload = $this->jwtEncoder->decode($token->getCredentials()))) { //line 96
        return false;
    }

    $event = new JWTDecodedEvent($payload);
    if ($this->dispatcher instanceof ContractsEventDispatcherInterface) {
        $this->dispatcher->dispatch($event, Events::JWT_DECODED);
    } else {
        $this->dispatcher->dispatch(Events::JWT_DECODED, $event);
    }

    if (!$event->isValid()) {
        return false;
    }

    return $payload;
}

$token is Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken type and its getCredentials() function's implementation returning empty array:

    /**
 * This is meant to be only an authenticated token, where credentials
 * have already been used and are thus cleared.
 *
 * {@inheritdoc}
 */
public function getCredentials()
{
    return [];
}

I cannot find a solution for it on Internet.

Thanks in advance

Upvotes: 0

Views: 2779

Answers (1)

Nuryagdy Mustapayev
Nuryagdy Mustapayev

Reputation: 775

It turns out that LexikJWTAuthenticationBundle bundle has its own implementation using Guard: JWTTokenAuthenticator And you can also extend it:

namespace App\Security\Guard;

use Lexik\Bundle\JWTAuthenticationBundle\Security\Guard\JWTTokenAuthenticator as BaseAuthenticator;

class JWTTokenAuthenticator extends BaseAuthenticator

{
    // Your own logic
}

In services.yml

# config/services.yaml
services:
    app.jwt_token_authenticator:
        class: App\Security\Guard\JWTTokenAuthenticator
        parent: lexik_jwt_authentication.security.guard.jwt_token_authenticator            
        #---below 3 lines are absent in documentation
        public: true
        autowire: true
        autoconfigure: false

Finally in security.yml:

security:
    # ...
    firewalls:
        # ...
        api:
            pattern:   ^/api
            stateless: true
            guard: 
                authenticators:
                    - app.jwt_token_authenticator

for further information check in here: Extending JWTTokenAuthenticator

Upvotes: 2

Related Questions