Comprendre les JSON Web Tokens : signer avec JWS

Dans la partie précédente, nous avons assemblé un en-tête et une charge utile. Seuls, ils ne prouvent rien. La signature est ce qui en fait quelque chose sur quoi un destinataire peut agir.

Ce qu’une signature vous apporte

La RFC 7515 définit JSON Web Signature. Elle vous donne l’intégrité, la charge utile n’a pas été altérée, et la non-répudiation, l’émetteur ne peut pas nier l’avoir écrite. Elle ne vous donne aucune confidentialité : la charge utile est en base64url, que n’importe qui peut décoder.

Les trois parties

La sérialisation compacte est la forme que tout le monde reconnaît : trois morceaux séparés par des points.

BASE64URL(header) . BASE64URL(payload) . BASE64URL(signature)

Ce qui est signé n’est pas la charge utile seule. C’est la chaîne header.payload, points compris, après encodage en base64url. Ce détail compte : il veut dire que l’en-tête est couvert par la signature, donc personne ne peut changer l’algorithme déclaré sans la casser.

En-têtes protégés et non protégés

JWS distingue deux jeux d’en-têtes. L’en-tête protégé est couvert par la signature. L’en-tête non protégé ne l’est pas : il voyage à côté, et n’importe qui peut le réécrire en vol.

La forme compacte n’a pas d’en-tête non protégé du tout, ce qui est une des raisons d’en faire le défaut sûr. Les formes JSON permettent les deux, et c’est là que les implémentations s’attirent des ennuis. Lisez ce qui arrive quand un vérificateur prend alg dans le mauvais : ce n’est pas théorique, c’était une vraie faille dans cette bibliothèque.

L’en-tête obligatoire

Un membre d’en-tête est exigé : alg, l’algorithme de signature. HS256 pour un HMAC avec SHA-256, RS256 pour RSASSA-PKCS1-v1_5, ES256 pour ECDSA sur P-256, EdDSA pour Ed25519. Lequel choisir mérite son propre article.

La spécification définit aussi alg: none, un jeton non signé. Ne l’acceptez jamais à la vérification. Un vérificateur qui honore la prétention d’un jeton à ne pas être signé accepte n’importe quoi.

Plusieurs signatures sur une charge utile

La sérialisation JSON autorise plus d’une signature sur la même charge utile, chacune avec son algorithme et sa clé. C’est ainsi que vous servez deux publics, l’un qui vérifie avec un secret partagé et l’autre avec une clé publique, sans émettre deux jetons.

La forme compacte ne sait pas l’exprimer. S’il vous le faut, il vous faut la forme JSON, et vous perdez la possibilité de mettre le jeton dans une URL.

La suite

Signer prouve qui a écrit la charge utile. Cela ne la cache pas. La partie suivante traite du chiffrement.