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?!