Comment ça marche ?
Le principe de fonctionnement des JWT
La génération d’un JWT peut se résumer en 3 étapes assez élémentaires :
- L’utilisateur se connecte depuis votre client qui va envoyer une requête HTTP au serveur (via l’API du serveur) avec, par exemple, un couple email/mot de passe
- Si les informations de connexion sont correctes, le serveur génère un jeton JWT
- Le serveur envoie le JWT généré au client, qui le conservera de son côté pour pouvoir le communiquer au serveur à chaque nouvelle requête
Ainsi, dès que le serveur reçoit une requête, si celle-ci contient un JWT, le serveur vérifiera la validité du JWT et saura quel utilisateur est à l’origine de la requête !
C’est aussi simple que ça 😃 L’idée, comme pour n’importe quelle méthode d’authentification, est simplement que le serveur puisse savoir « qui » (i.e. quel utilisateur) est à l’origine d’une requête. C’est pourquoi on appelle cela un jeton d’authentification. De plus, on pourra ajouter dans ce jeton des informations plus spécifiques sur les droits de l’utilisateur connecté : on pourra alors utiliser les JWT comme jetons d’autorisation (en plus de l’authentification) !
Concrètement, un JWT, c'est quoi ?
Petit rappel, JWT est l’acronyme de JSON Web Token, ce qui nous donne déjà un bon indice sur ce qu’est concrètement un JWT. Pour aller plus loin, JSON est lui-même l’acronyme de JavaScript Object Notation.
Ainsi, JWT prendra la forme d’un objet JSON qui contiendra un ensemble de paramètres et de valeurs. Voici à quoi pourrait ressembler l’objet, au format JSON, d’un utilisateur d’une application :
{“id”: “1234”, “username”: “PrimFX”, “email”: “primfx@example.com“}
Un JWT se décompose en 3 parties :
- Le Header : il contient les informations d’en-tête de notre jeton décrites par les deux champs suivants :
- alg: Indique l’algorithme utilisé pour signer (ou encrypter) le JWT. HS256 (HMAC + SHA256) est le plus communément utilisé.
- typ: Indique le type d’objet dont il s’agit. Pour un JWT Token, ce sera systématiquement “JWT”
- Le Payload : ce sont les données principales de notre jeton. Le Payload peut contenir des informations personnalisées (comme l’objet JSON présenté ci-dessus) ainsi que quelques paramètres prédéfinis optionnels appelés Claims (e.g. iss, exp, iat, etc.) : nous y reviendrons dans la section sur la sécurité des JWT.
- La Signature : cette dernière partie permettra au serveur d’assurer la conformité et validité d’un jeton
Le JWT n’est donc ni plus ni moins qu’un objet JSON décomposé en 3 parties distinctes. Et puisqu’on ne peut pas faire transiter un objet JSON « brute » dans des requêtes HTTP entre client et serveur, les JWT sont toujours encodés en Base64 afin de pouvoir être communiqués sous forme de chaînes de caractères ! Ainsi, voici à quoi ressemblera notre JWT :
A droite, on peut voir les trois sections Header, Payload et Signature de notre JWT (au format JSON). A gauche, il s’agit du JWT encodé en Base64 (où chaque section est indiquée par code couleur).
Des jetons transmis à chaque requête
Finalement, le JWT sera transmis à chaque requête du client au serveur dans les Headers (en-têtes) des requêtes HTTP. Plus précisément, le JWT devra être transmis dans le champ Authorization des Headers de la requête. Il devra également respecter le format de chaîne de caractère “Bearer ”. Pour que ce soit plus parlant, voici un petit exemple de requête HTTP (en JavaScript) avec son en-tête contenant un JWT ainsi que quelques données :
// Code JavaScript : exécute une requête HTTP POST sur https://example.com en passant le JWT dans les Headers
fetch('https://example.com', {
method: 'POST',
body: JSON.stringify({
param1: 'valeur1',
param2: 'valeur2',
etc: 'etc'
}),
headers: {
'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7ImlkIjoiMTIzNCIsInVzZXJuYW1lIjoiUHJpbUZYIiwiZW1haWwiOiJwcmltZnhAZXhhbXBsZS5jb20ifSwiaWF0IjoxNTkyNDIzNTAxfQ.OVj3A02xao5gyPgZY33b8QX7KtnkbmoFd6GbBnkwNVE'
}
});
Comme vous le voyez ici, le JWT se passe belle et bien comme une simple chaîne de caractères, rien de bien compliqué.
A présent, voici un aperçu de la requête HTTP générée par ce code JavaScript — on retrouve bien le Authorization Bearer contenant notre JWT :