La sécurisation des APIs et autres applications Web sur un développement Symfony peut être basée sur JWT – JSON Web Tokens.
Qu’est que JWT ?
Pour déployer la sécurisation JWT sur une application Symfony 4 on utilise ici le bundle : LexikJWTAuthenticationBundle
Le principe d’authentification JSON Web Tokens est de retourner un token chiffré grâce à une clé secrète (en utilisant l’algorithme HMAC) ou en utilisant des clés de chiffrements de type SHA256 ou ECDSA par exemple.
Le token comporte directement les information client tel que le username.
Ainsi on évite de stocker des informations relative au token côté serveur.
D’un point de vu Client / Serveur :
Le client envoie via un formulaire d’authentification son couple : username et mot de passe. En retour, le serveur va envoyer un token contenant le username.
En effet, le username est directement encodé dans le token grâce à la clé privé (SHA256) qui aura été préalablement générée sur le serveur.
Le client possède en retour son token. Ce token est conservé du coté client (localStorage ou cookie) et est envoyé à chaque requête vers le serveur.
Ainsi, à chaque requête, le serveur décrypte le token toujours grâce à la clé privée de manière à récupérer directement et simplement le username. De plus, le token contient une signature permettant de s’assurer que le contenu n’a pas été altéré par le client.
Installation du bundle LexikJWTAuthenticationBundle
Via composer
Depuis la console terminal dans le répertoire du projet concerné, on tape :
-> composer require lexik/jwt-authentication-bundle
Composer va se charger d’installer les différents packages utiles
Génération de la clé privé
Pour cette étape, il convient de lancer le terminal (pour mac ou linux)
$ mkdir -p config/jwt
$ openssl genrsa -out config/jwt/private.pem -aes256 4096
$ openssl rsa -pubout -in config/jwt/private.pem -out config/jwt/public.pem
Faites attention à conserver le mot de passe renseigné lors de la seconde commande. Ce dernier est nécessaire pour finaliser la configuration du bundle.
Configuration du bundle
Il est à présent nécessaire d’indiquer au bundle où se situe les clés à utiliser pour générer le token JWT.
Commencez par créer le fichier config/packages/lexik_jwt_authentication.yaml s’il n’est pas déjà présent.
Ce fichier doit contenir : le chemin vers la clé privée, le chemin vers la clé publique ainsi que le mot de passe utilisé pour générer ces dernières.
La bonne pratique étant d’utiliser les variables d’environnement pour stocker ces informations, le contenu du fichier est le suivant :
Il est ensuite nécessaire d’ajouter les différentes informations dans le fichier .env afin de pouvoir les utiliser.
Attention ! Il ne faut pas mettre dans ce fichier le mot de passe de la clé ayant été utilisé pour générer les clés de production.
Il est important de générer un jeu de clés différent pour votre serveur de production et de stocker les informations dans les variables d’environnement du serveur.
Configuration du security.yaml
Note : il faut supprimer la ligne : in_memory: { memory: ~ } dans les providers
Configuration de la route
Afin de pouvoir générer le token JWT, il est nécessaire d’implémenter la fonction correspondant à la route définie par check_path dans l’étape précédemment (/api/login_check).
Cette fonction doit retourner un json contenant les informations que l’on souhaite transmettre via le token (le username et les rôles dans l’exemple ci-dessous)
Génération d’un token – test
Directement depuis la fenêtre terminal, vous pouvez taper :
curl -X POST -H « Content-Type: application/json » http://localhost/api/login_check -d ‘{« username »: »johndoe », »password »: »test »}’
Si l’authentification échoue, vous aurez :
-> {« code »:401, »message »: »Bad credentials »}
Si l’authentification réussit, ça sera le token :
-> { « token » : « eyJhbciOiJSUzI1NiIsInR5cCI6IkpXUyJ9.eyJleHAiOjE0MzQ3Mjc1MzYsInVzZXJuYW1lIjoia29ybGVvbiIsImlhdCI6IjE0MzQ2NDExMzYifQ.nh0L_wuJy6ZKIQWh6OrW5hdLkviTs1_bau2GqYdDB0Yqy_RplkFghsuqMpsFls8zKEErdX5TYCOR7muX0aQvQxGQ4mpBkvMDhJ4-pE4ct2obeMTr_s4X8nC00rBYPofrOONUOR4utbzvbd4d2xT_tj4TdR_0tsr91Y7VskCRFnoXAnNT-qQb7i7HIBTbutb9zVStOFejrb4aLbr7Fl4byeIEYgp2Gd7gY » }
L’avantage d’utiliser JWT
Le partage d’authentification entre différentes applications ou APIs sur différents serveurs, ne se résume que par l’utilisation de la même clé privé pour encrypter le token et ainsi, les « username » sont bien partagés entre les différentes APIs ou application Web.