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.
Prérequis :
- Une application Symfony avec Api Platform
- Avoir installé la Symfony CLI (Debian)
- Avoir installé Composer (Debian)
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.
Source :
https://api-platform.com/docs/core/jwt/