PyJWT

A Python implementation of RFC 7519 (JSON Web Tokens)

https://pyjwt.readthedocs.io/

JSON Web Tokens (JWTs)

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

https://tools.ietf.org/html/rfc7519

Introduction Video:

https://jwt.io/introduction/

Important!

JWT contents are:

  • Signed (using HMAC or key pair)
  • Not Encrypted!

Used For

  • Authentication
  • Information exchange

Token Structure

Three-part string: xxxx.yyyy.zzzz

  • Header
  • Payload
  • Signature

Example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

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

Payload

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

Signature

HMAC SHA256

  • base64UrlEncode(header) + "." + base64UrlEncode(payload)
  • secret

Claims

  • Reserved
    • iss (issuer)
    • iat (issued time)
    • exp (expiration)
    • sub (subject)
  • Public (registered)
  • Private

Example Payload

{
   # 'Private' claims:
   'actions': [
       'get',
       'complete',
       ],
   # JWT reserved claims:
   'sub': thing_id,
   'iat': datetime.utcnow(),
   'exp': datetime.utcnow() + token_ttl,
   'iss': 'CLEPY',
}

Installing

pip install PyJWT


In [ ]:
# Imports

import jwt
from datetime import datetime, timedelta

In [ ]:
# Settings

token_ttl = timedelta(days=1)
secret = 'This is a totally insecure secret.'

In [ ]:
# Payload

thing_id = 1234

payload = {
    'actions': [
                'get',
                'complete',
                ],
    'sub': thing_id,
    'iat': datetime.utcnow(),
    'exp': datetime.utcnow() + token_ttl,
    'iss': 'CLEPY',
    }
payload

In [ ]:
# Encode

token = jwt.encode(payload, secret)
token

In [ ]:
# Decode

jwt.decode(token, key=secret)

In [ ]:
# Don't Verify

options = {
           'verify_signature': False,
           }
jwt.decode(token, options=options)

In [ ]:
# Shorter TTL

short_ttl = timedelta(seconds=10)
payload2 = {
    'actions': [
                'get',
                'complete',
                ],
    'sub': thing_id,
    'iat': datetime.utcnow(),
    'exp': datetime.utcnow() + short_ttl,
    'iss': 'CLEPY',
    }
token2 = jwt.encode(payload2, secret)
token2

In [ ]:
# Try after 10s

jwt.decode(token2, key=secret)

In [ ]:
# Ignore sig and exp

options = {
           'verify_signature': False,
           'verify_exp': False,
           }
jwt.decode(token2, options=options)

In [ ]:
# Verify issuer

jwt.decode(token, key=secret, issuer='CLEPY')

More info

https://jwt.io/