Connaissez-vous vraiment JWT ?

A propos

de moi

Karim Pinchon

 

  • Développeur backend
  • @kpn13
  • https://blog.karimpinchon.com

Quelques

concepts

de base

Jeton / Token

C'est quoi un jeton ?

  • chaine de caractères
  • authentification
  • autorisation
  • ...

ça a quelle forme ?

ça sert à quoi ?

Une simple chaine ?

Référence

Valeur

JSON Web Token

https://jwt.io/

JSON Web Token

"JOT"

The suggested pronunciation of JWT is the same as the English word "jot".

RFC 7519

La cryptographie

C'est quoi la cryptographie ?

  • mathématiques
  • confiance
  • communication
  • canal non sûr
  • CAIN (entre autres)

Signature numérique

  • intégrité
  • authentification
  • non répudiation

Chiffrement

  • confidentialité

Hachage

  • intégrité
  • sens unique

MAC / HMAC

  • MAC (Message Authentication Code)
  • HMAC (Hash-Based ...)
  • intégrité
  • authentification

Encodage

  • registre de caractères

A quoi ça ressemble?

jwt.io

token.dev

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJteSBzZXJ2ZXIiLCJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkthcmltIFBJTkNIT04iLCJpYXQiOjE2MTk4NjI0NzUsImF1ZCI6IkFGVVBEYXkgTGlsbGUvUmVubmVzIDIwMjEiLCJleHAiOjE2MjIyNDYzOTksImp0aSI6IjdhMzY1ZGQwLTdiYzctNDg5NC1iYjA5LTc3MWVhMTUyY2M1NSJ9.KqQZVQdyxIv70mc2U2f78g41IVr94GHU_JM7LYBMxqU

JSON Web Token (JWT)

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJteSBzZXJ2ZXIiLCJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkthcmltIFBJTkNIT04iLCJpYXQiOjE2MTk4NjI0NzUsImF1ZCI6IkFGVVBEYXkgTGlsbGUvUmVubmVzIDIwMjEiLCJleHAiOjE2MjIyNDYzOTksImp0aSI6IjdhMzY1ZGQwLTdiYzctNDg5NC1iYjA5LTc3MWVhMTUyY2M1NSJ9.KqQZVQdyxIv70mc2U2f78g41IVr94GHU_JM7LYBMxqU

JSON Web Token (JWT)

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

{
  "iss": "my server",
  "sub": "1234567890",
  "name": "Karim PINCHON",
  "iat": 1619862475,
  "aud": "Devoxx France 2022",
  "exp": 1622246399,
  "jti": "7a365dd0-7bc7-4894-bb09-771ea152cc55"
}

HMACSHA256(
  base64UrlEncode(      ) + "." +
  base64UrlEncode(payload),
  UN_SECRET)

entête

charge utile

.

.

header

signature

{
  "payload":"ewogICJpc3MiOiAibXkgc2VydmVyIiwKICAic3ViIjogIjEyMzQ1Njc4OTAiLAogICJuYW1lIjogIkthcmltIFBJTkNIT04iLAogICJpYXQiOiAxNjE5ODYyNDc1LAogICJhdWQiOiAiQUZVUERheSBMaWxsZS9SZW5uZXMgMjAyMSIsCiAgImV4cCI6IDE2MjIyNDYzOTksCiAgImp0aSI6ICI3YTM2NWRkMC03YmM3LTQ4OTQtYmIwOS03NzFlYTE1MmNjNTUiCn0K",
  "protected":"eyJhbGciOiJSUzI1NiJ9",
  "signature":"ZbJXgzuYVCQCqoUxa5OtWRqmsl2S3Pe-29P19KacZgXlymwi-G-w6n-dnZObTPbheJbnlbptvv8yWO_pEqnohZZXH_c7Sd5sEm5k58-6GqG1FE13Q2CmWA44V91YbHA0rpMhiA1GNxVHIdNpW9wNkzEM3aqbJ9sdhix2RsbS3ofBWQdyaFSDrazWWCAK17ghI5KlUK_KQWNlXDZd8dn7VMNGBRuA5N4erfftG6i-OtFODYR_R1Eb0ltGBYOZamLOxtwR8PR40vjLGtQwJdp8CxdKXKHvrzahRA6k3YRYT2U8dzCsDPYFuzUAZgiSZ5JEG5favYWQsiyg84wF35jIdA"
}

JSON serialization format

(oui oui c'est aussi un JWT)

Focus sur l'entête

{
  "typ":"JWT",
  "alg":"HS256",
  "jku":"https://key.service.com/keys.json",
  "jwk":"...",
  "kid":"ebb58a6d-0c84-4b5e-aac3-f5edc600cd77",
  "x5u":"https://key.service.com/keys.pem",
  "x5c":"...",
  "x5t":"bcb0923eacb242cf0e69e626cd7ca2fc3426fae0",
  "x5t#S256":"dbb821587583647e905b94764c86eb9f85bad06ced4087256bfcee19c7e44389",
  "cty":"jwk+json",
  "crit":["exp"]
}

Entête

Focus sur

la charge utile

"Registered claims"

(tout ça c'est optionnel)

{
  "iss":"émetteur du jeton",
  "aud":"le destinataire du jeton",
  "sub":"le sujet du jeton",
  "iat":"la date d'émission du jeton",
  "nbf":"à partir de quelle date il est valide",
  "exp":"quand le jeton expire",
  "jti":"identifiant unique du jeton"
}

"Public claims"

https://www.iana.org/assignments/jwt/jwt.xhtml

"Private claims"

Go

JOSE

JOSE

Javascript Object Signing and Encryption

JSON Web Token

  • RFC 7519
  • "claims" entre plusieurs parties

JSON Web Signature

  • RFC 7515
  • jeton signé

JSON Web Encryption

  • RFC 7516
  • jeton chiffré

JSON Web Algorithms

  • RFC 7518
  • algorithmes

JSON Web Key

  • RFC 7517
  • clés

Voyons

JWE

JSON Web Encryption (JWE)

eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ.uWmje_-Y3GF2nzjLzPopD17yHB7WBDrQgPeE011dhep40Hg4sE6-ZbqBgc4K4cwfbsXU-ZwTY5b6RiHa8clNtZZW2_Qm1Mbu8jcXs-84OrL9n9t7CgdTBd1lGp8e5j6bAxBJTjwdOWO6Cz492DVAxxNNMyuV0UIJsgEUo8b5IpLD4j2VvOgE_V8FSMuifEsq13OKORjfQ2wApIZDw1QAhXQ9GLx08Nl-0umEcaiXH8f36Pqvt4dRwK6tSIgSMht3qAXNCtBBFQS8fyffu1KyZ8_11gWlQdeisPhKbDGEDBNd2SAN2-lQxrcCBmyJ3oD0PCeS3sV8fvoM4eFRfzYhpg.lI2L7mB4nXr4Lnsk.pkdYMTeQUjmBd5kGUnLL72n4ztIQaotAsy1MQj7180sMkGzNwq9n8mI-1bhpavxgAczRhGfKXSmHfHsF3curt10ClMZOsHOJ8sP93lura_5pU7ZYB0V2stupb6a8IiWWYOdASpjtsKr0VpKRO_AuiaRGC1WZdlhWHnptIP78bkG2P7hV57ht3W-upjIErnRtEY29Vt7ddu-r983l8MLw2-8-jb31LxgJYS2Zkr7eDB-UmI5xygsEHLH_pdqOKqxJhO3U3LkWBlt7a1sH.SzRYiT21_Lv7ae8xxmmfRg

Compact serialization format

JSON Web Encryption (JWE)

eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ.uWmje_-Y3GF2nzjLzPopD17yHB7WBDrQgPeE011dhep40Hg4sE6-ZbqBgc4K4cwfbsXU-ZwTY5b6RiHa8clNtZZW2_Qm1Mbu8jcXs-84OrL9n9t7CgdTBd1lGp8e5j6bAxBJTjwdOWO6Cz492DVAxxNNMyuV0UIJsgEUo8b5IpLD4j2VvOgE_V8FSMuifEsq13OKORjfQ2wApIZDw1QAhXQ9GLx08Nl-0umEcaiXH8f36Pqvt4dRwK6tSIgSMht3qAXNCtBBFQS8fyffu1KyZ8_11gWlQdeisPhKbDGEDBNd2SAN2-lQxrcCBmyJ3oD0PCeS3sV8fvoM4eFRfzYhpg.lI2L7mB4nXr4Lnsk.pkdYMTeQUjmBd5kGUnLL72n4ztIQaotAsy1MQj7180sMkGzNwq9n8mI-1bhpavxgAczRhGfKXSmHfHsF3curt10ClMZOsHOJ8sP93lura_5pU7ZYB0V2stupb6a8IiWWYOdASpjtsKr0VpKRO_AuiaRGC1WZdlhWHnptIP78bkG2P7hV57ht3W-upjIErnRtEY29Vt7ddu-r983l8MLw2-8-jb31LxgJYS2Zkr7eDB-UmI5xygsEHLH_pdqOKqxJhO3U3LkWBlt7a1sH.SzRYiT21_Lv7ae8xxmmfRg

Compact serialization format

JSON Web Encryption (JWE)

Compact serialization format

BASE64URL(UTF8(JWE Protected Header)).
BASE64URL(JWE Encrypted Key).
BASE64URL(JWE Initialization Vector).
BASE64URL(JWE Ciphertext).
BASE64URL(JWE Authentication Tag)
{
   "protected":"eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ",
   "encrypted_key":"uWmje_-Y3GF2nzjLzPopD17yHB7WBDrQgPeE011dhep40Hg4sE6-ZbqBgc4K4cwfbsXU-ZwTY5b6RiHa8clNtZZW2_Qm1Mbu8jcXs-84OrL9n9t7CgdTBd1lGp8e5j6bAxBJTjwdOWO6Cz492DVAxxNNMyuV0UIJsgEUo8b5IpLD4j2VvOgE_V8FSMuifEsq13OKORjfQ2wApIZDw1QAhXQ9GLx08Nl-0umEcaiXH8f36Pqvt4dRwK6tSIgSMht3qAXNCtBBFQS8fyffu1KyZ8_11gWlQdeisPhKbDGEDBNd2SAN2-lQxrcCBmyJ3oD0PCeS3sV8fvoM4eFRfzYhpg",
   "iv":"lI2L7mB4nXr4Lnsk",
   "ciphertext":"pkdYMTeQUjmBd5kGUnLL72n4ztIQaotAsy1MQj7180sMkGzNwq9n8mI-1bhpavxgAczRhGfKXSmHfHsF3curt10ClMZOsHOJ8sP93lura_5pU7ZYB0V2stupb6a8IiWWYOdASpjtsKr0VpKRO_AuiaRGC1WZdlhWHnptIP78bkG2P7hV57ht3W-upjIErnRtEY29Vt7ddu-r983l8MLw2-8-jb31LxgJYS2Zkr7eDB-UmI5xygsEHLH_pdqOKqxJhO3U3LkWBlt7a1sH",
   "tag":"SzRYiT21_Lv7ae8xxmmfRg"
}

JSON Web Encryption (JWE)

JSON serialization format

Et le reste...

La gestion

des clés

JSON Web Key

{
  "alg":"A128KW",
  "kty":"oct",
  "k":"GawgguFyGrWKav7AX4VKUg"
}

Exemple de représentation d'une clé symétrique

(c'est la RFC 7517)

JSON Web Key

{
  "keys":
  [
    {
      "kty":"oct",
      "alg":"A128KW",
      "k":"GawgguFyGrWKav7AX4VKUg"
    },
    {
      "kty":"oct",
      "k":"AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75
     aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow",
     "kid":"HMAC key used in JWS spec Appendix A.1 example"
    }
  ]
}

Exemple de représentation d'un set de clés symétriques

{
    "alg": "HS256",
    "type": "JWT",
    "kid": "6d3db68d-5867-458d-921b-1c2426ef78b4"
}

Exemple d'utilisation du kid

JSON Web Key

JSON Web Key

{
  "alg": "RS256",
  "x5u": "https://key.service.com/key.pem"
}

Exemple d'utilisation de certificat X509

(de la même manière on peut utiliser l'attribut x5c pour embarqué le certificat dans le jeton)

JSON Web Key

{
    "alg": "HS256",
    "type": "JWT",
    "kid": "6d3db68d-5867-458d-921b-1c2426ef78b4",
    "jku": "https://key.service.com/keys.json"
}

Exemple d'utilisation JWK set URL

Et le reste...

A quoi

ça sert ?

Jeton d'API

OAuth2

OpenID Connect

Session stateless

Usage "custom"

Et les

attaques ?

Jeton non sécurisé

{
    "alg": "none",
    "type": "JWT"
}

Entête

RSA public key as shared key

Brute force

Modification des données chiffrées

Substitution

Le paradoxe de JWT

Quelques

conseils
de sécurité

Le secret

Ne pas

tout accepter

Valider

les claims

Préférer l'asymétrique

Utiliser

une librairie

existante et

éprouvée

Ne vous battez pas pour révoquer les JWT

A propos de
confidentialité

Les informations contenues dans un JWS sont lisibles

par tout le monde

Eviter de "logger"

les jetons

Mettre les informations

nécessaires et suffisantes

Quelles

sont les
alternatives?

CleverCloud/biscuit

"authentication and authorization token for microservices architectures"

paragonie/paseto

Platform-Agnostic Security Tokens

rescrv/libmacaroons

"Cookies with Contextual Caveats for Decentralized Authorization in the Cloud"

(image

non officielle...)

tuupola/branca

"Authenticated and encrypted API tokens using modern crypto."

(pas plus

officielle...)

Il est temps

de conclure !

Pour résumer

Merci à tous pour votre attention !

Karim PINCHON - @kpn13

https://slides.com/kpn13