Pour comprendre comment fonctionne l’authentification par jeton, on peut faire une comparaison avec les sessions en PHP.
Sous PHP, lorsqu’un utilisateur se connecte à un site web :
- Le serveur crée une session pour cet utilisateur
- Le serveur génère un identifiant de session unique pour cet utilisateur
- Le serveur stocke cet identifiant de session dans un cookie sur le navigateur de l’utilisateur, par défaut sous le nom
PHPSESSID
- L’utilisateur envoie cet identifiant de session dans chaque requête HTTP pour identifier l’utilisateur, puisque les cookies sont envoyés automatiquement dans chaque requête HTTP
PHP, par défaut, va stocker les identifiants de session dans sa mémoire vive, ce qui signifie que les sessions sont stockées en mémoire et sont perdues lorsque le serveur redémarre (On peut aussi stocker les sessions dans des fichiers ou dans une base de données pour les conserver entre les redémarrages).
Cette solution permet de gérer les cas classiques de connexion/déconnexion d’un utilisateur.
Cependant, ce type de fonctionnement ne permet pas de partager facilement un même compte pour s’authentifier sur plusieurs plateformes distinctes.
Jetons JWT
- Les jetons JWT quant à eux sont stateless
- Cela signifie que les informations des sessions ouvertes ne sont pas stockées côté serveur
- Outre le gain de mémoire, les jetons JWT peuvent être utilisés pour utiliser les mêmes comptes utilisateurs pour plusieurs applications.
- Il suffira que les applications utilisent la même clé privée pour signer et vérifier les jetons JWT
- Les utilisateurs pourront ainsi s’authentifier une fois sur l’application hébergeant les comptes utilisateurs, puis ils pourront se connecter aux autres applications, celles-ci n’ayant qu’à vérifier la validité des jetons.
- Ils seront renvoyés avec chaque requête HTTP au serveur
- Les informations contenues dans le jeton sont signées à l’aide d’une clé privée détenue par le serveur
- Quand le serveur reçoit à nouveau le jeton, le serveur compare la signature envoyée par le client et celle qu’il aura générée avec sa propre clé privée et à comparer les résultats
- Si les signatures sont identiques, le jeton est valide.
Structure d’un jeton JWT
Un jeton JWT est composé de trois parties séparées par des points .
:
- Header : Contient le type du jeton et l’algorithme de cryptage utilisé, par exemple :
{"alg": "HS256", "typ": "JWT"}
- Payload : Contient les informations de l’utilisateur, par exemple :
{"sub": "1234567890", "name": "John Doe", "iat": 1516239022}
- Signature : Permet de vérifier l’intégrité du jeton, par exemple :
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
La signature est donc générée à partir de la concaténation des parties Header et Payload encodées en Base64, soit, par exemple, avec la clé privée QDdazfAZf1213%dsqùdsq
:
1HMACSHA256(2 base64UrlEncode({ alg: "HS256", typ: "JWT" }) +3 "." +4 base64UrlEncode({ sub: "1234567890", name: "John Doe", iat: 1516239022 }),5 "QDdazfAZf1213%dsqùdsq"6);
Donnera un jeton JWT du type :
1eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0ODA5MjkyODIsImV4cCI6MTQ4MDkzMjg2OCwibmFtZSI6IlVzZXJuYW1lIn0.gZeuWNbjO8kyEX92AjgX5oLy5qhu6YWTPr6vtYELZQ4
Signature des jetons JWT
Il existe plusieurs algorithmes de signature pour les jetons JWT, parmi lesquels :
- HS256 : HMAC avec SHA-256
- HS384 : HMAC avec SHA-384
- HS512 : HMAC avec SHA-512
Il est important de noter que les jetons JWT ne sont pas chiffrés, mais signés. Cela signifie que les informations contenues dans le jeton sont lisibles par n’importe qui, mais que la signature permet de vérifier l’intégrité du jeton.
Cas d’utilisation
Les jetons JWT peuvent être utilisés principalement de deux manières côté client :
- stocké dans un cookie
- stocké dans le sessionStorage (ou le localStorage) du navigateur
Chacune de ces solutions présente des avantages et des inconvénients en termes de sécurité et de fonctionnalité :
- Cookie : Les cookies sont envoyés automatiquement par le navigateur dans chaque requête HTTP, ce qui permet de gérer facilement l’authentification des utilisateurs. Cependant, les cookies peuvent être volés par des attaquants via des attaques de type Cross-Site Scripting (XSS) ou Cross-Site Request Forgery (CSRF).
- sessionStorage : Le sessionStorage est stocké localement dans le navigateur et n’est pas envoyé automatiquement dans chaque requête HTTP. Cela signifie que l’application doit gérer manuellement l’envoi du jeton JWT dans chaque requête HTTP (Par exemple, via le header
Authorization: Bearer <jeton>
) . Le sessionStorage est plus sécurisé que les cookies car il n’est pas envoyé automatiquement dans chaque requête HTTP.
Inconvénients
Les jetons JWT présentent également quelques inconvénients :
- Taille : Les jetons JWT peuvent être assez volumineux, en particulier si les informations de l’utilisateur sont stockées dans le jeton. Cela peut entraîner des problèmes de performance si les jetons sont envoyés dans chaque requête HTTP.
- Sécurité : Les jetons JWT sont signés, mais pas chiffrés. Cela signifie que les informations contenues dans le jeton sont lisibles par n’importe qui. Il est donc important de ne pas stocker d’informations sensibles dans le jeton.
- Expiration : Les jetons JWT peuvent être configurés pour expirer après une certaine durée. Cela signifie que l’utilisateur doit se reconnecter régulièrement pour obtenir un nouveau jeton JWT.
- Expiration 2 : Si un compte utilisateur doit être bloqué, il faudra attendre que le jeton expire pour que le blocage soit effectif.
- Révocation : Les jetons JWT ne peuvent pas être révoqués une fois qu’ils ont été émis. Cela signifie que si un jeton est volé, il peut être utilisé indéfiniment par l’attaquant.
Pour solutionner en partie les problèmes listés ci-dessus, certaines librairies mettent en place des mécanismes supplémentaires permettant entre autres de rafraîchir des sessions ou de forcer la ré-authentification d’un utilisateur si nécessaire.
Ajout de l’authentification par jeton à notre API
Le temps de ce module ne permettant pas de mettre en place en détail l’authentification par jeton, nous allons utiliser une librairie pour gérer les jetons JWT.
Cependant, pour pouvoir utiliser cette librairie, il est nécessaire de mettre en place une base de données pour stocker les utilisateurs et les mots de passe.
Nous reviendrons donc sur ce point par la suite.