Que sont les jetons Web JSON (JWT) ? Pourquoi les API les utilisent-elles ?

0
64
Shutterstock.com/TierneyMJ

Le JSON La norme Web Tokens (JWT) décrit une méthode compacte pour les transferts de données vérifiables. Chaque jeton contient une signature qui permet à la partie émettrice de vérifier l'intégrité du message.

Dans cet article, vous apprendrez ce que la structure JWT inclut et comment vous pouvez générer vos propres jetons. . Les JWT sont un moyen populaire de sécuriser les API et d'authentifier les sessions utilisateur, car ils sont simples et autonomes.

Fonctionnement des JWT

L'une des tâches les plus courantes de toute API consiste à valider que les utilisateurs sont bien ceux qu'ils prétendent être. L'authentification est généralement gérée en demandant au client d'inclure une clé API avec les requêtes qu'il envoie au serveur. La clé contient des informations intégrées qui identifient l'utilisateur. Cela laisse encore une grande question : comment le serveur peut-il valider qu'il a émis la clé en premier lieu ?

Les JWT résolvent facilement ce problème en utilisant un secret pour signer chaque jeton. Le serveur peut vérifier la validité d'un jeton en essayant de recalculer la signature présentée à l'aide de son secret privé. Toute altération entraînera l'échec de la vérification.

Le format JWT

Les JWT sont formés de trois composants distincts :

  • En-tête – Cela inclut les métadonnées sur le jeton lui-même, telles que l'algorithme de signature qui a été utilisé.
  • Charge utile– La charge utile du jeton peut être n'importe quelle donnée arbitraire pertinente pour votre système. Il peut inclure l'identifiant de l'utilisateur et une liste des fonctionnalités avec lesquelles il peut interagir.
  • Signature – La signature permet de valider ultérieurement l'intégrité du jeton. Il est créé en signant l'en-tête et la charge utile à l'aide d'une valeur secrète connue uniquement du serveur.

Ces trois composants sont associés à des points pour produire le JWT :

header.payload.signature

Chaque pièce est encodée en Base-64. Le jeton complet est une chaîne de texte qui peut être facilement consommée dans des environnements de programmation et envoyée avec des requêtes HTTP.

Création d'un JWT

Les étapes pour créer un JWT peut être implémenté dans tous les langages de programmation. Cet exemple utilise PHP mais le processus sera similaire dans votre propre système.

Commencez par créer l'en-tête. Cela inclut généralement deux champs, alg et typ :

  • alg – L'algorithme de hachage qui sera utilisé pour créer la signature. Il s'agit normalement de HMAC SHA256 (HS256).
  • tapez – Type de jeton généré. Cela devrait être JWT.

Voici le JSON qui définit l'en-tête :

{ "alg" : "HS256", "typ" : " JWT" }

L'en-tête JSON doit ensuite être encodé en Base64 :

$headerData = ["alg" => "HS256", "type" => "JWT"]; $header = base64_encode(json_encode($headerData));

Définissez ensuite la charge utile de votre jeton comme un autre objet JSON. Ceci est spécifique à l'application. L'exemple fournit des détails sur le compte d'utilisateur authentifié, ainsi que des informations sur le jeton lui-même. exp, iat et nbf sont des champs utilisés par convention pour exprimer l'heure d'expiration du jeton, émis à l'heure et non valide avant l'heure (de début). La charge utile doit également être encodée en Base64.

$payloadData = [ "ID utilisateur" => 1001, "nom d'utilisateur" => "démo", "fonctionnalités sous licence" => "todos", "calendrier", "facturation"], "exp" => (temps() + 900), "iat" => temps(), "nbf" => temps() ]; $payload = base64_encode(json_encode($payloadData));

Il ne reste plus qu'à créer la signature. Pour produire cela, vous combinez d'abord l'en-tête et la charge utile en une seule chaîne séparée par un . caractère :

$headerAndPayload = "$header.$payload";

Ensuite, vous devez générer un secret unique à utiliser comme clé de signature. Le secret doit être stocké en toute sécurité sur votre serveur et ne doit jamais être envoyé aux clients. L'exposition de cette valeur permettrait à n'importe qui de créer des jetons valides.

//Méthode PHP pour générer 32 caractères aléatoires $secret = bin2hex(openssl_random_pseudo_bytes(16));

Vous terminez le processus en utilisant le secret pour signer l'en-tête combiné et la chaîne de charge utile à l'aide de l'algorithme de hachage que vous avez indiqué dans l'en-tête. La signature de sortie doit être encodée en Base64 comme les autres composants.

$signature = base64_encode(hash_hmac("sha256", $headerAndPayload, $secret, true));

Vous avez maintenant l'en-tête, la charge utile et la signature en tant que composants textuels individuels. Rejoignez-les tous avec . séparateurs pour créer le JWT à envoyer à votre client :

$jwt = "$header.$payload.$signature";

Vérifier les JWT entrants

L'application cliente peut déterminer les fonctionnalités disponibles pour l'utilisateur en décodant la charge utile du jeton. Voici un exemple en JavaScript :

const tokenComponents = jwt.split("."); charge utile const = jeton[1]; const payloadDecoded = JSON.parse(atob(charge utile));   //["todos", "calendar", "invoicing"] console.log(payloadDecoded.licensedFeatures);

Un attaquant pourrait réaliser que ces données sont en texte brut et semblent faciles à modifier. Ils pourraient essayer de convaincre le serveur qu'ils disposent d'une fonctionnalité bonus en modifiant la charge utile du jeton dans leur prochaine requête :

//Crée un nouveau composant de charge utile const modifiedPayload = btoa(JSON.stringify({ …charge utileDécodée, sous licenceFonctionnalités : ["todos", "calendar", "invoicing", "extraPremiumFeature"] }));   //Assemblez le JWT avec l'en-tête et la signature d'origine const newJwt = `${token[0]}.${modifiedPayload}.${ token[2]}`

La réponse à la façon dont le serveur se défend contre ces attaques réside dans la méthode utilisée pour générer la signature. La valeur de la signature prend en compte l'en-tête et la charge utile du jeton. La modification de la charge utile, comme dans cet exemple, signifie que la signature n'est plus valide.

Le code côté serveur vérifie les JWT entrants en recalculant leurs signatures. Le jeton a été falsifié si la signature envoyée par le client ne correspond pas à la valeur générée sur le serveur.

$tamperedToken = $_POST["apiKey"]; liste($en-tête, $charge utile, $signature) = $tamperedToken ;   //Déterminez la signature que ce jeton *devrait* avoir //lorsque le secret du serveur est utilisé comme clé $expectedSignature = hash_hmac("sha256", "$header.$payload", $secret, true) ;   //Le jeton a été falsifié car sa //signature est incorrecte pour les données qu'il contient if ($signature !== $expectedSignature) { http_response_code(403); } //Les signatures correspondent – nous avons généré ce //jeton et pouvons faire confiance à ses données autrement { $user = fetchUserById($payload["userId"]); }

Il est impossible pour un attaquant de générer un jeton valide sans avoir accès au secret du serveur. Cela signifie également qu'une perte accidentelle – ou rotation délibérée – du secret invalidera immédiatement tous les jetons précédemment émis.

Dans une situation réelle, votre code d'authentification doit également inspecter l'expiration et "pas avant" horodatages dans la charge utile du jeton. Ceux-ci sont utilisés pour déterminer si la session de l'utilisateur est toujours valide.

Quand utiliser les JWT

Les JWT sont fréquemment utilisés pour l'authentification API car ils sont simples à mettre en œuvre sur le serveur, faciles à utiliser sur le client et simples à transmettre au-delà des limites du réseau. Malgré leur simplicité, ils offrent une bonne sécurité car chaque jeton est signé à l'aide de la clé secrète du serveur.

Les JWT sont un mécanisme sans état, vous n'avez donc pas besoin d'enregistrer des informations sur les jetons émis sur votre serveur. Vous pouvez obtenir des informations sur le client qui présente un JWT à partir de la charge utile du jeton, au lieu d'avoir à effectuer une recherche dans une base de données. Ces informations peuvent être fiables en toute sécurité une fois que vous avez vérifié la signature du jeton.

L'utilisation de JWT est un bon choix chaque fois que vous avez besoin d'échanger des informations entre deux parties sans risque de falsification. Il y a cependant des points faibles à prendre en compte : l'ensemble du système sera compromis si la clé secrète de votre serveur est divulguée ou si votre code de vérification de signature contient un bogue. Pour cette raison, de nombreux développeurs choisissent d'utiliser une bibliothèque open source pour implémenter la génération et la validation JWT. Des options sont disponibles pour tous les langages de programmation courants. Ils éliminent le risque d'oubli lorsque vous vérifiez vous-même les jetons.

Résumé

La norme JWT est un format d'échange de données qui inclut une vérification d'intégrité intégrée. Les JWT sont couramment utilisés pour sécuriser les interactions entre les serveurs d'API et les applications clientes. Le serveur peut faire confiance aux jetons entrants s'il est capable de reproduire leurs signatures. Cela permet d'effectuer des actions en toute sécurité à l'aide des informations obtenues à partir de la charge utile du jeton.

Les JWT sont pratiques mais ils présentent certains inconvénients. La représentation textuelle encodée en Base64 d'un JWT peut rapidement devenir volumineuse si vous avez plus d'une poignée de champs de charge utile. Cela pourrait devenir une surcharge inacceptable lorsque votre client doit envoyer le JWT avec chaque requête.

L'apatridie des JWT est également un autre inconvénient potentiel : une fois qu'ils sont émis, les jetons sont immuables et doivent être utilisés. tels quels jusqu'à leur expiration. Les clients qui utilisent les charges utiles JWT pour déterminer les autorisations ou les fonctionnalités sous licence d'un utilisateur devront obtenir un nouveau jeton du backend chaque fois que leurs attributions changent.

LIRE LA SUITE

  • &rsaquo ; Il est normal de lésiner sur ces 10 produits technologiques
  • &rsaquo ; 10 fonctionnalités iPad géniales que vous devriez utiliser
  • › Maj+Entrée est un raccourci secret que tout le monde devrait connaître
  • › Examen du clavier mécanique Keychron Q8 : un clavier avancé pour toutes les utilisations
  • &rsaquo ; 10 fonctionnalités cachées d'Android 13 que vous auriez pu manquer
  • &rsaquo ; Test du Lenovo ThinkPad Z13 Gen 1 : un ordinateur portable en cuir végétalien qui signifie affaires