Accueil » Authentification JWT Api Platform

Authentification JWT Api Platform

Dans cette procédure, je vous explique comment mettre en place l’authentification JWT avec Api Platform et Symfony 6. Le token contient l’identifiant de l’utilisateur (Plus d’informations sur le token JWT). Nous allons également ajouter l’authentification dans Swagger et OpenApi.

Logo Api Platform

Prérequis :

Authentification JWT avec Api Platform :

Dans un premier temps, nous allons ajouter le bundle « LexikJWTAuthenticationBundle » dans notre projet :

composer require jwt-auth

Puis nous allons générer une paire de clés :

symfony console lexik:jwt:generate-keypair

Ensuite nous allons modifier le fichier config/packages/security.yaml :

security:
    password_hashers:
        Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
    providers:
        app_user_provider:
            entity:
                class: App\Entity\User
                property: email
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            lazy: true
            provider: app_user_provider
            json_login:
                check_path: /authentication_token
                username_path: email
                password_path: password
                success_handler: lexik_jwt_authentication.handler.authentication_success
                failure_handler: lexik_jwt_authentication.handler.authentication_failure
            jwt: ~

    access_control:
        - { path: ^/api, roles: PUBLIC_ACCESS } # Allows accessing the Swagger UI
        - { path: ^/authentication_token, roles: PUBLIC_ACCESS }
        - { path: ^/, roles: IS_AUTHENTICATED_FULLY }

when@test:
    security:
        password_hashers:
            Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
                algorithm: auto
                cost: 4 # Lowest possible value for bcrypt
                time_cost: 3 # Lowest possible value for argon
                memory_cost: 10 # Lowest possible value for argon

Puis nous allons déclarer la nouvelle route d’authentification dans le fichier config/routes.yaml :

controllers:
    resource: ../src/Controller/
    type: attribute
    
authentication_token:
    path: /authentication_token
    methods: ['POST']

Ensuite nous allons ajouter l’identifiant de notre token JWT dans le fichier config/packages/lexik_jwt_authentication.yaml :

lexik_jwt_authentication:
    secret_key: '%env(resolve:JWT_SECRET_KEY)%'
    public_key: '%env(resolve:JWT_PUBLIC_KEY)%'
    pass_phrase: '%env(JWT_PASSPHRASE)%'
    user_identity_field: email

Puis nous allons ajouter l’autorisation d’authentification par token JWT dans Swagger en créant le fichier config/packages/api_platform.yaml :

api_platform:
    swagger:
         api_keys:
             JWT:
                name: Authorization
                type: header

Ensuite on va créer un Endpoint dans Swagger qui va permettre de récupérer le token JWT. On va créer le fichier src/OpenApi/JwtDecorator.php :

<?php

namespace App\OpenApi;

use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface;
use ApiPlatform\OpenApi\OpenApi;
use ApiPlatform\OpenApi\Model;

final class JwtDecorator implements OpenApiFactoryInterface
{
    public function __construct(
        private OpenApiFactoryInterface $decorated
    ) {}

    public function __invoke(array $context = []): OpenApi
    {
        $openApi = ($this->decorated)($context);
        $schemas = $openApi->getComponents()->getSchemas();

        $schemas['Token'] = new \ArrayObject([
            'type' => 'object',
            'properties' => [
                'token' => [
                    'type' => 'string',
                    'readOnly' => true,
                ],
            ],
        ]);
        $schemas['Credentials'] = new \ArrayObject([
            'type' => 'object',
            'properties' => [
                'email' => [
                    'type' => 'string',
                    'example' => 'johndoe@example.com',
                ],
                'password' => [
                    'type' => 'string',
                    'example' => 'apassword',
                ],
            ],
        ]);

        $schemas = $openApi->getComponents()->getSecuritySchemes() ?? [];
        $schemas['JWT'] = new \ArrayObject([
            'type' => 'http',
            'scheme' => 'bearer',
            'bearerFormat' => 'JWT',
        ]);
        
        $pathItem = new Model\PathItem(
            ref: 'JWT Token',
            post: new Model\Operation(
                operationId: 'postCredentialsItem',
                tags: ['Token'],
                responses: [
                    '200' => [
                        'description' => 'Get JWT token',
                        'content' => [
                            'application/json' => [
                                'schema' => [
                                    '$ref' => '#/components/schemas/Token',
                                ],
                            ],
                        ],
                    ],
                ],
                summary: 'Get JWT token to login.',
                requestBody: new Model\RequestBody(
                    description: 'Generate new JWT Token',
                    content: new \ArrayObject([
                        'application/json' => [
                            'schema' => [
                                '$ref' => '#/components/schemas/Credentials',
                            ],
                        ],
                    ]),
                ),
                security: [],
            ),
        );
        $openApi->getPaths()->addPath('/authentication_token', $pathItem);

        return $openApi;
    }
}

Ensuite on enregistre le service dans le fichier config/service.yaml :

parameters:

services:
    _defaults:
        autowire: true
        autoconfigure: true

    App\:
        resource: '../src/'
        exclude:
            - '../src/DependencyInjection/'
            - '../src/Entity/'
            - '../src/Kernel.php'

    App\OpenApi\JwtDecorator:
            decorates: 'api_platform.openapi.factory'
            arguments: ['@.inner']

L’authentification JWT est désormais disponible avec un endpoint spécifique dans Swagger.

Authentification JWT Api Platform - Endpoint JWT

Source :

https://api-platform.com/docs/core/jwt/

Susceptible de vous intéresser :