Let’s Talk About JWT
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
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiZ2l2ZW5fbmFtZSI6Ikplc3NpY2EiLCJmYW1pbHlfbmFtZSI6IlRlbXBvcmFsIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiamVzc3RlbXBvcmFsIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1NTIzMDU3MTB9.LmUNPW9fSAqVTGEEFW0yrsD9eooyRv_VPB3r6tCWkRc
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiZ2l2ZW5fbmFtZSI6Ikplc3NpY2EiLCJmYW1pbHlfbmFtZSI6IlRlbXBvcmFsIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiamVzc3RlbXBvcmFsIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1NTIzMDU3MTB9.LmUNPW9fSAqVTGEEFW0yrsD9eooyRv_VPB3r6tCWkRc
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiZ2l2ZW5fbmFtZSI6Ikplc3NpY2EiLCJmYW1pbHlfbmFtZSI6IlRlbXBvcmFsIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiamVzc3RlbXBvcmFsIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1NTIzMDU3MTB9.LmUNPW9fSAqVTGEEFW0yrsD9eooyRv_VPB3r6tCWkRc
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiZ2l2ZW5fbmFtZSI6Ikplc3NpY2EiLCJmYW1pbHlfbmFtZSI6IlRlbXBvcmFsIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiamVzc3RlbXBvcmFsIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1NTIzMDU3MTB9.LmUNPW9fSAqVTGEEFW0yrsD9eooyRv_VPB3r6tCWkRc
@jesstemporal
jesstemporal.com
{
"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
HMACSHA256(
encodeBase64(header) + "." +
encodeBase64(payload),
"your-256-bit-secret"
)
The Signature
@jesstemporal
jesstemporal.com
HMACSHA256(
encodeBase64(header) + "." +
encodeBase64(payload),
"nPilVwFjcF0v5NL5YT1xsiwRJCGqM1do"
)
The Signature
Symmetrical algorithm
🤫
@jesstemporal
jesstemporal.com
Asymmetrical algorithm
🔑🗝
@jesstemporal
jesstemporal.com
JSON Web Key
@jesstemporal
jesstemporal.com
RFC 7517
@jesstemporal
jesstemporal.com
@jesstemporal
jesstemporal.com
JWK
{
"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'
jwt.decode(
token,
key='my_super_secret',
algorithms=['HS256', ]
)
import jwt
token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MjQyIiwibmFtZSI6Ikplc3NpY2EgVGVtcG9yYWwiLCJuaWNrbmFtZSI6Ikplc3MifQ.izbq1mT_GXp-39o-JEm1i1W1FcYBIaX3a5c4ZwRzXhE'
jwt.decode(
token,
key='my_super_secret',
algorithms=['HS256', ]
)
# {"sub": "4242", "name": "Jessica Temporal", "nickname": "Jess"}
import jwt
token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiIsIm5hbWUiOiJKZXNzIFRlbXBvcmFsIiwiZXhwIjoxNTE2MjM5MDIyfQ.uqeQ60enLaCQEZ-7C0d_cgQSrWfgXRQuoB1LZD0j06E'
jwt.decode(
token,
key='my_super_secret',
algorithms=['HS256', ]
)
import jwt
token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiIsIm5hbWUiOiJKZXNzIFRlbXBvcmFsIiwiZXhwIjoxNTE2MjM5MDIyfQ.uqeQ60enLaCQEZ-7C0d_cgQSrWfgXRQuoB1LZD0j06E'
jwt.decode(
token,
key='my_super_secret',
algorithms=['HS256', ]
)
# ExpiredSigureError: Signature Expired
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'
import jwt
from cryptography.hazmat.primitives import serialization
token = 'eyJ0eXAiOiJK...81gVns6I_j4kSuyuRxlAJBe3pHi-yS2'
public_key = open('.ssh/id_rsa.pub', 'r').read()
import jwt
from cryptography.hazmat.primitives import serialization
token = 'eyJ0eXAiOiJK...81gVns6I_j4kSuyuRxlAJBe3pHi-yS2'
public_key = open('.ssh/id_rsa.pub', 'r').read()
key = serialization.load_ssh_public_key(public_key.encode())
import jwt
from cryptography.hazmat.primitives import serialization
token = 'eyJ0eXAiOiJK...81gVns6I_j4kSuyuRxlAJBe3pHi-yS2'
public_key = open('.ssh/id_rsa.pub', 'r').read()
key = serialization.load_ssh_public_key(public_key.encode())
jwt.decode(jwt=token, key=key, algorithms=['RS256', ])
# {'sub': '4242', 'name': 'Jessica Temporal', 'nickname': 'Jess'}