Aller au contenu

Apiplatform TokenValidator Lexik

De Marmits Wiki

Pour utiliser la classe TokenValidator dans API Platform, vous devez l’intégrer dans le processus de validation des tokens JWT reçus dans les requêtes. Voici comment vous pouvez procéder :


1. Créer un EventListener ou un Decorator

Vous pouvez créer un EventListener pour intercepter les requêtes entrantes et valider le token JWT avant qu’API Platform ne traite la requête.

a. Créer la classe TokenValidator

Voici un exemple de la classe TokenValidator que vous avez mentionnée :

namespace App\Service;

use Jose\Component\Core\AlgorithmManager;
use Jose\Component\Core\JWK;
use Jose\Component\Signature\Algorithm\RS256;
use Jose\Component\Signature\JWSVerifier;

class TokenValidator
{
    private $jwsVerifier;

    public function __construct()
    {
        $algorithmManager = new AlgorithmManager([new RS256()]);
        $this->jwsVerifier = new JWSVerifier($algorithmManager);
    }

    public function validateToken(string $token, JWK $jwk): bool
    {
        return $this->jwsVerifier->verifyWithKey($token, $jwk, 0);
    }
}

b. Créer un EventListener pour valider le token

Créez un EventListener qui écoute les événements de requête et valide le token JWT.

namespace App\EventListener;

use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpFoundation\JsonResponse;
use App\Service\TokenValidator;
use Jose\Component\Core\JWK;

class TokenValidationListener
{
    private $tokenValidator;

    public function __construct(TokenValidator $tokenValidator)
    {
        $this->tokenValidator = $tokenValidator;
    }

    public function onKernelRequest(RequestEvent $event): void
    {
        $request = $event->getRequest();

        // Récupérer le token JWT de l'en-tête Authorization
        $authHeader = $request->headers->get('Authorization');
        if (!$authHeader || !preg_match('/Bearer\s(\S+)/', $authHeader, $matches)) {
            $event->setResponse(new JsonResponse(['error' => 'Token missing'], 401));
            return;
        }

        $token = $matches[1];

        // Charger la clé publique (JWK) depuis Keycloak ou un autre fournisseur
        $jwk = JWK::create([
            'kty' => 'RSA',
            'n' => 'your-public-key-modulus', // Remplacez par la clé publique
            'e' => 'AQAB', // Exposant public
        ]);

        // Valider le token
        if (!$this->tokenValidator->validateToken($token, $jwk)) {
            $event->setResponse(new JsonResponse(['error' => 'Invalid token'], 401));
        }
    }
}

c. Enregistrer l’EventListener

Enregistrez l’EventListener dans config/services.yaml :

services:
    App\EventListener\TokenValidationListener:
        tags:
            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }

2. Utiliser un Decorator pour le JWT Authenticator

Si vous utilisez LexikJWTAuthenticationBundle, vous pouvez décorer son authentificateur pour ajouter votre logique de validation.

a. Créer un Decorator

Créez une classe qui décore l’authentificateur JWT de Lexik.

namespace App\Security;

use Lexik\Bundle\JWTAuthenticationBundle\Security\Authenticator\JWTAuthenticator;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use App\Service\TokenValidator;
use Jose\Component\Core\JWK;

class CustomJWTAuthenticator extends JWTAuthenticator
{
    private $tokenValidator;

    public function __construct(JWTAuthenticator $decorated, TokenValidator $tokenValidator)
    {
        parent::__construct(
            $decorated->getJWTokenManager(),
            $decorated->getEventDispatcher(),
            $decorated->getTokenExtractor()
        );
        $this->tokenValidator = $tokenValidator;
    }

    public function supports(Request $request): ?bool
    {
        return parent::supports($request);
    }

    public function getCredentials(Request $request)
    {
        $credentials = parent::getCredentials($request);

        // Valider le token avec TokenValidator
        $jwk = JWK::create([
            'kty' => 'RSA',
            'n' => 'your-public-key-modulus', // Remplacez par la clé publique
            'e' => 'AQAB', // Exposant public
        ]);

        if (!$this->tokenValidator->validateToken($credentials['token'], $jwk)) {
            throw new AuthenticationException('Invalid token');
        }

        return $credentials;
    }
}

b. Enregistrer le Decorator

Enregistrez le Decorator dans config/services.yaml :

services:
    App\Security\CustomJWTAuthenticator:
        decorates: lexik_jwt_authentication.security.jwt_authenticator
        arguments:
            $decorated: '@.inner'
            $tokenValidator: '@App\Service\TokenValidator'

3. Configurer API Platform pour utiliser l’authentification JWT

Dans config/packages/security.yaml, assurez-vous que le pare-feu est configuré pour utiliser JWT :

security:
    enable_authenticator_manager: true
    providers:
        jwt_provider:
            lexik_jwt: ~

    firewalls:
        api:
            pattern: ^/api
            stateless: true
            jwt: ~

    access_control:
        - { path: ^/api/login, roles: PUBLIC_ACCESS }
        - { path: ^/api, roles: ROLE_USER }

4. Tester la validation du token

  • Envoyez une requête à votre API avec un token JWT valide dans l’en-tête Authorization.
  • Si le token est invalide, vous devriez recevoir une réponse 401 Unauthorized.

Exemple de requête avec curl :

curl -X GET http://localhost:8000/api/your-endpoint \
     -H "Authorization: Bearer your.jwt.token"

5. Documentation supplémentaire


Voir Apiplatform Keycloak Lexik


source:DeepSeek