Let’s Talk About JWT

Hello!

Disclaimer

@jesstemporal

jesstemporal.com

@jesstemporal

jesstemporal.com

JWT

"Jot"

@jesstemporal

jesstemporal.com

JWT

JSON Object Signing and Encryption - JOSE

@jesstemporal

jesstemporal.com

RFC 7519

@jesstemporal

jesstemporal.com

Usually is a standardized string that represents information

@jesstemporal

jesstemporal.com

JSON Web Token

@jesstemporal

jesstemporal.com

JSON Web Token

@jesstemporal

jesstemporal.com

JSON Web Token

@jesstemporal

jesstemporal.com

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiZ2l2ZW5fbmFtZSI6Ikplc3NpY2EiLCJmYW1pbHlfbmFtZSI6IlRlbXBvcmFsIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiamVzc3RlbXBvcmFsIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1NTIzMDU3MTB9.LmUNPW9fSAqVTGEEFW0yrsD9eooyRv_VPB3r6tCWkRc

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiZ2l2ZW5fbmFtZSI6Ikplc3NpY2EiLCJmYW1pbHlfbmFtZSI6IlRlbXBvcmFsIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiamVzc3RlbXBvcmFsIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1NTIzMDU3MTB9.LmUNPW9fSAqVTGEEFW0yrsD9eooyRv_VPB3r6tCWkRc

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiZ2l2ZW5fbmFtZSI6Ikplc3NpY2EiLCJmYW1pbHlfbmFtZSI6IlRlbXBvcmFsIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiamVzc3RlbXBvcmFsIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1NTIzMDU3MTB9.LmUNPW9fSAqVTGEEFW0yrsD9eooyRv_VPB3r6tCWkRc

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiZ2l2ZW5fbmFtZSI6Ikplc3NpY2EiLCJmYW1pbHlfbmFtZSI6IlRlbXBvcmFsIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiamVzc3RlbXBvcmFsIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1NTIzMDU3MTB9.LmUNPW9fSAqVTGEEFW0yrsD9eooyRv_VPB3r6tCWkRc

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

The header

@jesstemporal

jesstemporal.com

{
  "sub": "1234567890",
  "given_name": "Jessica",
  "family_name": "Temporal",
  "preferred_username": "jesstemporal",
  "iat": 1516239022,
  "exp": 1552305710
}

The Payload

@jesstemporal

jesstemporal.com

{
  "sub": "1234567890",
  "iss": "https://jtemporal.com",
  "iat": 1516239022,
  "exp": 1552305710
}

Reserved claims

@jesstemporal

jesstemporal.com

{
  "given_name": "Jessica",
  "family_name": "Temporal",
  "preferred_username": "jesstemporal"
}

Public claims

@jesstemporal

jesstemporal.com

{
  "anything": "you want",
  "really": "anything"
}

Private claims

@jesstemporal

jesstemporal.com

Keep it small,

only relevant data

@jesstemporal

jesstemporal.com

Don't put sensitive data in the payload

@jesstemporal

jesstemporal.com

HMACSHA256(
    encodeBase64(header) + "." +
    encodeBase64(payload),
    "your-256-bit-secret"
)

The Signature

@jesstemporal

jesstemporal.com

HMACSHA256(
    encodeBase64(header) + "." +
    encodeBase64(payload),
    "nPilVwFjcF0v5NL5YT1xsiwRJCGqM1do"
)

The Signature

@jesstemporal

jesstemporal.com

Symmetrical algorithm

🤫

@jesstemporal

jesstemporal.com

Asymmetrical algorithm

🔑🗝

@jesstemporal

jesstemporal.com

JSON Web Key

@jesstemporal

jesstemporal.com

RFC 7517

@jesstemporal

jesstemporal.com

JWK

@jesstemporal

jesstemporal.com

{
  "keys": [{
     "alg": "RS256",
     "kty": "RSA",
     "use": "sig",
     "n": "uEOPrkjGKxE...YIwS5ZoDQ",
     "e": "AQAB",
     "kid": "n6OFo...9cl9",
     "x5t": "ET...rQA",
     "x5c": ["MIIDDTCCAf...OaeyleoS0="]
  }]
}

JWTs in Python

with PyJWT

@jesstemporal

jesstemporal.com

import jwt

token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MjQyIiwibmFtZSI6Ikplc3NpY2EgVGVtcG9yYWwiLCJuaWNrbmFtZSI6Ikplc3MifQ.izbq1mT_GXp-39o-JEm1i1W1FcYBIaX3a5c4ZwRzXhE'
import jwt

token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MjQyIiwibmFtZSI6Ikplc3NpY2EgVGVtcG9yYWwiLCJuaWNrbmFtZSI6Ikplc3MifQ.izbq1mT_GXp-39o-JEm1i1W1FcYBIaX3a5c4ZwRzXhE'

jwt.get_unverified_header(token)
import jwt

token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiIsIm5hbWUiOiJKZXNzIFRlbXBvcmFsIiwiZXhwIjoxNTE2MjM5MDIyfQ.uqeQ60enLaCQEZ-7C0d_cgQSrWfgXRQuoB1LZD0j06E'

jwt.decode(
    token,
    key='my_super_secret',
    algorithms=['HS256', ]
)
import jwt

from cryptography.hazmat.primitives import serialization

token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI0MjQyIiwibmFtZSI6Ikplc3NpY2EgVGVtcG9yYWwiLCJuaWNrbmFtZSI6Ikplc3MifQ.HgHJPl6b5W0CiDz4cNuyRcs5B3KgaoRbMvZBgCkcXOSOCAc0m7R10tSm6d86u8oW8NgzGoIAlKxBw0CIPhdx5N7MWTE2gshzQqhuq5MB9tNX1pYrLsiOMbibeMasvcf97Kd3JiLAzPPJe6XXB4PNL4h_4RcW6aCgUlRhGMPx1eRkGxAu6ndp5zzWiHQH2KVcpdVVdAwbTznLv3OLvcZqSZj_zemj__IAZPMkBBnhdjYPn-44p9-xrNmFZ9qBth4Ps1ZC1_A6lH77Mi1zb48Ou60SUT1-dhKLU09yY3IX8Pas6xtH6NbZ-e3FxjofO_OL47p25CvdqMYW50JVit2tjU6yzaoXde8JV3J40xuQqwZeP6gsClPJTdA-71PBoAYbjz58O-Aae8OlxfWZyPsyeCPQhog5KjwqsgHUQZp2zIE0Y50CEfoEzsSLRUbIklWNSP9_Vy3-pQAKlEpft0F-xP-fkSf9_AC4-81gVns6I_j4kSuyuRxlAJBe3pHi-yS2'

Where to find JWTs?

@jesstemporal

jesstemporal.com

Access token

@jesstemporal

jesstemporal.com

RFC 9068

@jesstemporal

jesstemporal.com

ID token

@jesstemporal

jesstemporal.com

 How to be safer with JWTs

@jesstemporal

jesstemporal.com

 Don't store JWTs in local storage

@jesstemporal

jesstemporal.com

 Don't verify JWTs in the front end

@jesstemporal

jesstemporal.com

 Don't put sensitive data in the JWT

@jesstemporal

jesstemporal.com

Tools

@jesstemporal

jesstemporal.com

jwt.io

 

@jesstemporal

jesstemporal.com

@jesstemporal

jesstemporal.com

Questions?!

Let’s Talk About JWT - PyCon2022

By Jessica Temporal

Let’s Talk About JWT - PyCon2022

JSON Web Tokens, or JWTs for short, are all over the web. They can be used to track bits of information about a user in a very compact way and can be used in APIs for authorization purposes. Join me and learn what JWTs are, what problems it resolves, and how you can use JWTs on your applications.

  • 444