OWASP et HTML5Mtl : Une introduction à JWT (JSON Web Tokens)

Logo HTML5Mtl

Avant de commencer : Un peu sur moi

Benoit Piette
  • Architecte de solutions Web
  • Dans le domaine depuis 1996
  • A travaillé pour CGI, Nurun, ACCEO, Tink
  • Mandats pour Molson, Loto-Québec, SAQ, Desjardins, Bombardier, Wizard of the Coast, Metro, CAE, Via Rail, AMT, Banque Nationale, AIMIA
  • Président Résoeuvra depuis 2015
  • Co-organisateur HTML5Mtl

Avant de commencer : Les références

Cette présentation reprend du contenu et suit plusieurs autres présentations et articles sur le Web. Vous trouverez de plus amples informations en y accédant. Elles sont toutefois en anglais :-) Les voici :

Qu'est que JWT ?

Authentification et autorisation sur le Web - Basic Authentication

Diagramme de séquence - Basic Auth
Diagramme de séquence - Basic Auth

Authentification et autorisation sur le Web - Basic Authentication


                        HTTP/1.1 401 Access Denied
                        WWW-Authenticate: Basic realm="Mon Serveur"
                        Content-Length: 0
                    

                        GET /info/ HTTP/1.1
                        Host: benoitpiette.com
                        Authorization: Basic Base64EncodedString
                    

Authentification et autorisation sur le Web - Cookie et sessions

Cette image n'est pas accessible, contient un diagramme de séquence explication l'authentification avec cookie
Authentification avec cookie

Authentification et autorisation sur le Web - Cookie et sessions


                        HTTP/1.1 302 Moved
                        Location: /login
                    

                        POST /login HTTP/1.1
                        Content-Type: application/x-www-form-urlencoded
                        Content-Length: 27
                        username=toto&password=tata
                    

                        HTTP/1.1 200 Ok
                        Set-Cookie: JSESSIONID=488q98r9q87r6q987r
                    

                        GET /info/ HTTP/1.1
                        Cookie: JSESSIONID=488q98r9q87r6q987r
                    

Authentification et autorisation sur le Web - Bearer et JWT

Diagramme de séquence - JWT
Diagramme de séquence - JWT

Authentification et autorisation sur le Web - Bearer et JWT


                        HTTP/1.1 401 Access Denied
                        WWW-Authenticate: Bearer realm="Mon Serveur"
                        Content-Length: 0
                    

                        POST /login HTTP/1.1
                        Content-Type: application/x-www-form-urlencoded
                        Content-Length: 27
                        username=toto&password=tata
                    

                        HTTP/1.1 200 Ok
                        {token:header.payload.signature}
                    

                        GET /info/ HTTP/1.1
                        Authorization: Bearer header.payload.signature
                    

Anatomie d'un JSON Web Token


                        aaaaaaa.bbbbbbbb.cccccccc
                    

Anatomie d'un JSON Web Token : L'en-tête / header


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

Anatomie d'un JSON Web Token : Le chargement / payload


                {
                  "sub": "1234567890",
                  "name": "John Doe",
                  "admin": true
                }
                    

Authentification par claims

Anatomie d'un JSON Web Token : payload, Registered Claims

Ils sont tous facultatifs.

iat:
Moment où le jeton a été émis.
iss:
L'émetteur du jeton
sub:
Le sujet du jeton
aud:
À qui s'adresse le jeton
exp:
Moment où le jeton expire. La date actuelle doit être avant ce moment.
nbf:
Moment où le jeton devient actif. Ne doit pas être accepté avant ce moment.
jti:
identifiant unique pour le jeton

Anatomie d'un JSON Web Token : la signature

La signature utilise un algorithme (ex: HMAC SHA256) où l'en-tête et le payload sont encodés, puis signés à partir d'un secret connu seulement de l'émetteur du jeton (serveur d'authentification) et du consommateur (l'application Web - côté serveur)


                    base64URLEncode (HMACSHA256 ( base64URLEncode (header) + "." +  base64URLEncode (payload)) )
                
Pseudo code de la portion signature du JWT

JWT et Cross Domain / CORS

Les appels AJAX CORS ne transportent pas toujours les cookies

Un JWT est ajouté au headers dans un XMLHttpRequest 2 et peut être utilisé dans un contexte CORS


                        xhr.setRequestHeader('Authorization','Bearer ' + JWTToken);
                    

CORS : Utiliser Ajax Cross Site


           res.writeHead(200, {"Context-Type" : "text/plain",
                    "Access-Control-Allow-Origin" : "*",
                    "Access-Control-Allow-Methods" :   "POST, GET, PUT, DELETE, OPTIONS",
                    "Access-Control-Allow-Credentials" :  false,
                    "Access-Control-Max-Age" :  '86400',
                    "Access-Control-Allow-Headers" : "Content-Type, Accept"
                    });
                    
Ajout des headers CORS en node.js

La nature stateless de JWT

Impact d'utiliser JWT sur la cache et la performance

Impact d'utiliser JWT sur le SEO et analytics

Comment garder en mémoire le JWT ?

sessionStorage.setItem("jwtToken", theToken);

Sécurité : XSRF ou XSS ?

XSRF
Tromper une application en faisant rejouer une requête dans le contexte de l'utilisateur connecté
XSS
Injection de code exécutable par le navigateur dans une application Web

Découplage de l'authentification de l'application Web / API

Expiration du JWT

Chiffrement du JWT

Encoding API


                    // Encodage de chaînes de catactères UTF-8
                    var encoder = new TextEncoder("utf-8");
                    // encode en arraybuffer de int8
                    var encodedText = encoder.encode("Bonjour le monde ééé");
                    // Décode en chaînes de catactères iso-8859-1
                    var decoder = new TextDecoder("iso-8859-1");
                    var decodedText = decoder.decode(encodedText);
                
Texte en UTF-8
Bonjour le monde ééé
Texte encodé puis décodé en ISO-8859-1

Web Crypto API


                    var crypto = window.crypto || window.msCrypto;
                

Web Crypto API - Exemple Hash SHA-1



                     function hashe() {
                         var encoder = new TextEncoder("utf-8");
                         // encode en arraybuffer de int8
                         var encodedText = encoder.encode(document.getElementById("el1").value);

                         window.crypto.subtle.digest(
                             {
                                 name: "SHA-1"
                             }, encodedText

                         ).then(function(hash){
                             var encodedHash = new Uint8Array(hash);
                             var decoder = new TextDecoder("utf-8");
                             var decodedText = decoder.decode(encodedHash);
                             document.getElementById("hashed").innerHTML =  decodedText;

                         }).catch(function(err){
                             console.error(err);
                         });
                     }
                     

JWT dans le cadre d'une application Angular.JS

Autres points à regarder

Librairies et outils

Standards JSON

Merci !!