Connaissez-vous vraiment JWT ?

A propos
De
Moi

  • Karim Pinchon
  • Développeur back (~10 ans)
  • Actuellement chez Ornikar
  • @kpn13

Je ne suis pas un cryptographe

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": "Symfony Live Paris 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"

Votez
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
Maintenant
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

https://github.com/lexik/LexikJWTAuthenticationBundle

OAuth2.0

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

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

(évidemment transiter via HTTPS

uniquement mais en 2022 on n'a plus

besoin de le dire hein ?)

Quelles
Sont les
Alternatives?

par

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) Pierre Tibulle @ptibulle

Remerciements

Merci à tous pour votre attention !

Karim PINCHON - @kpn13

Connaissez-vous vraiment JWT ? - Symfony Live 2022

By Karim PINCHON

Connaissez-vous vraiment JWT ? - Symfony Live 2022

  • 862