Apprendre à protéger des documents avec JSON Web Token (JWT)

Daria Lapikhina

Pour réagir au contenu de cet article, un espace de dialogue vous est proposé sur le forum. Commentez

- Titre : Apprendre à protéger des documents avec JSON Web Token (JWT)

- Auteur : Daria Lapikhina

- Parution : 2 novembre 2021

- Licence : Copyright ® 2021 Daria Lapikhina . Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction

- II. Mise en place de JSON Web Token (ou JWT)

- II-A. Un peu de théorie pour les développeurs débutants

- II-B. Comment implémenter JWT

- III. Remerciements Developpez.com

I - Introduction

Une suite bureautique en ligne ONLYOFFICE Docs peut s’intégrer à n’importe quelle plateforme en utilisant les connecteurs prêts à l’emploi ou développés par les partenaires. Nous avons déjà montré comment installer les éditeurs en ligne ONLYOFFICE et les intégrer à des applications WEB.

Dans ce tutoriel, nous allons vous montrer comment protéger vos documents contre les accès non autorisés, à l'aide d'un jeton Web JSON, lors d’une intégration des éditeurs de documents en ligne à votre application.

II - Mise en place de JSON Web Token (ou JWT)

ONLYOFFICE utilise JSON Web Token (ou JWT) pour protéger l'échange de données entre les éditeurs, leurs services internes et le stockage. Les éditeurs ONLYOFFICE demandent une signature cryptée qui est ensuite hébergée dans le jeton. Ce jeton valide le droit d'effectuer une certaine opération avec les données.

Si vous voulez utiliser JWT, il est préférable d'utiliser un package prêt à l'emploi. Mais cette fois, nous allons tout faire nous-mêmes pour comprendre comment cela fonctionne.

II-A - Un peu de théorie pour les développeurs débutants

JWT est composé de trois parties :

- header - contient des méta-informations, par exemple, un algorithme de cryptage ;

- payload - contient les informations ;

- signature - créée à partir du header et du payload générés et d’un code secret.

Ces trois parties sont des objets JSON, tandis que le jeton JSON lui-même est une base64url de toutes les parties reliées par des points.

Voici comment cela fonctionne :

1. Serveur 1 détecte une signature basée sur une clef et une chaîne de caractères de header.payload ;

2. Jeton header.payload.signature est formé ;

3. Serveur 2 reçoit ce jeton, forme sa signature basée sur les deux premières parties de celui-ci ;

4. Serveur 2 compare le jeton généré avec celui reçu ; s'ils correspondent, alors les données n'ont pas été falsifiées.

II-B - Comment implémenter JWT

Les éditeurs permettent de transférer le jeton JWT dans le corps de la demande et dans le header. Il est préférable d'utiliser le corps de la requête, car la taille du header est limitée. Mais nous allons considérer les deux variantes.

Si vous transférez le jeton dans le corps de la requête, la charge utile ressemblera à ceci :

{
"key": "value"
}

Et si vous le transférez dans le header :

{
"payload": {
"key": "value"
}
}

Après, nous ajoutons une clef au fichier config.json.

"jwt_secret": "supersecretkey"

Pour démarrer les éditeurs avec JWT, il suffit de spécifier des variables d'environnement :

docker run -i -t -d -p 9090:80 -e JWT_ENABLED=true -e JWT_SECRET=supersecretkey onlyoffice/documentserver

Si vous envisagez de transférer le jeton dans le corps de la requête, ajoutez une variable supplémentaire -e JWT_IN_BODY=true

docker run -i -t -d -p 9090:80 -e JWT_ENABLED=true -e JWT_SECRET=supersecretkey -e JWT_IN_BODY=true onlyoffice/documentserver

Le fichier app/jwtManager.js contient toute la logique pour travailler avec JWT. Nous avons seulement besoin d'ajouter le jeton à la configuration lorsque les éditeurs sont ouverts.

if (jwt.isEnabled()) {
editorConfig.token=jwt.create(editorConfig);
}

Le jeton est formé par l'algorithme ci-dessus dans la section théorique. Voici la fonction :

1. function create(payloadObj) {

2. if (!isEnabled()) return null;

4. var headerObj = {

5. alg: "HS256",

6. typ: "JWT"

7. };

9. header = b64Encode(headerObj);

10. payload = b64Encode(payloadObj);

11. hash = calculateHash(header, payload);

13. return header + "." + payload + "." + hash;

14. }

16. function calculateHash(header, payload) {

17. return b64UrlEncode(crypto.createHmac("sha256", cfg.jwt_secret).update(header + "." + payload)

18. .digest("base64"));

19. }

Cela nous permettra d'ouvrir un document, mais nous devons également vérifier le jeton reçu de Document Server.

Nous allons vérifier à la fois le corps et l'en-tête. La fonction est assez simple, elle lancera une erreur si quelque chose ne va pas. Sinon, elle vérifiera un jeton et fusionnera le corps de la requête avec le contenu du jeton.

1. function checkJwtToken(req) {

2. if (!jwt.isEnabled()) return;

3. var token = req.body.token;

4. var inBody = true;

6. if (!token && req.headers.authorization) {

7. token = req.headers.authorization.substr("Bearer ".length);

8. inBody = false;

9. }

11. if (!token) throw new Error("Expected JWT token");

13. var payload = jwt.verify(token);

15. if (!payload) throw new Error("JWT token validation failed");

17. if (inBody) {

18. Object.assign(req.body, payload);

19. } else {

20. Object.assign(req.body, payload.payload);

21. }

22. }

La fonction qui effectue la vérification est elle aussi très simple.

1. function verify(token) {

2. if (!isEnabled()) return null;

3. if (!token) return null;

5. var parts = token.split(".");

6. if (parts.length != 3) {

7. return null;

8. }

10. var hash = calculateHash(parts[0], parts[1]);

11. if (hash !== parts[2]) return null;

12. return b64Decode(parts[1]);

13. }

Les méthodes de jwtManager :

La méthode de création permet d'obtenir un objet avec des données, par exemple :

{
"key": "value"
}

Construit le header de JWT

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

Ensuite, la méthode prend les deux objets, crée une représentation en chaîne JSON et l'encode en base64url. Elle relie ensuite les deux lignes avec des points et forme une signature basée sur votre clef. Dans cet exemple, nous allons utiliser supersecretkey.

Le résultat est ce jeton : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ2YWx1ZSJ9.ozm44FMRAlWXB0PhJg935wyOkp7wtj1jXvgEGIS0iig

La méthode de vérification reçoit le jeton, sépare ses parties en utilisant des points, prend les deux premières parties et crée une signature. Ensuite, elle compare la signature générée avec celle reçue. Si elles correspondent, la charge utile est décodée et l'objet JSON est renvoyé.

Vous pouvez également jouer avec token, voir comment il est construit et trouver des bibliothèques open source pour différents langages ici.

Veuillez noter qu'il s'agit d'une mise en œuvre minimale de JWT. La norme est vaste et comporte toutes sortes d'éléments à prendre en considération, par exemple, la durée de vie limitée du jeton. Nous recommandons donc d'utiliser des paquets prêts à l'emploi pour travailler avec JWT en production.

Nous espérons que cet exemple vous aidera à protéger par JWT vos documents. Vous pouvez également trouver plus d'informations sur l'implémentation de JWT dans la documentation de l'API ONLYOFFICE.

III - Remerciements Developpez.com

Nous tenons à remercier Malick pour la mise au gabarit et escartefigue pour la relecture orthographique.