Skip to content

Instantly share code, notes, and snippets.

@darelf
Last active April 13, 2022 21:24
Show Gist options
  • Save darelf/190bc97b29e91509534d7535ebde4762 to your computer and use it in GitHub Desktop.
Save darelf/190bc97b29e91509534d7535ebde4762 to your computer and use it in GitHub Desktop.
Python 3 JWT
"""
Functions for creating and verifying authentication tokens
according to the `JWT spec <https://jwt.io/>`_.
JWT authentication tokens are made of three sections that are
Base64Url encoded with no padding. The third section is an HMAC
of the first two sections, so that without knowing the secret
key you cannot verify the token nor create tokens that will be
accepted on the other end.
>>> from jwt import jwt
>>> token = jwt.create_signed_token(b'secret',
... {
... 'value': 'a value',
... 'other': 'This is some other value',
... 'verified': True
... })
>>> (v, p) = jwt.verify_signed_token(b'secret', token)
>>> v
True
>>> p['value']
'a value'
>>> p['verified']
True
"""
import base64
import hmac
import json
def create_signed_token(key, data):
"""
Create a complete JWT token. Exclusively uses sha256
HMAC.
>>> token = jwt.create_signed_token(b'secret',
... {
... 'value': 'a value',
... 'other': 'This is some other value',
... 'verified': True
... })
>>> len(token)
185
"""
header = json.dumps({'typ': 'JWT', 'alg': 'HS256'}).encode('utf-8')
henc = base64.urlsafe_b64encode(header).decode().strip('=')
payload = json.dumps(data).encode('utf-8')
penc = base64.urlsafe_b64encode(payload).decode().strip('=')
hdata = henc + '.' + penc
d = hmac.new(key, hdata.encode('utf-8'), 'sha256')
dig = d.digest()
denc = base64.urlsafe_b64encode(dig).decode().strip('=')
token = hdata + '.' + denc
return token
def verify_signed_token(key, token):
"""
Decodes the payload in the token and returns a tuple
whose first value is a boolean indicating whether the
signature on this token was valid, followed by the
decoded payload.
>>> token = 'eyJ0eXAiOiAiSldUIiwgImFsZyI6ICJIUzI1NiJ9.eyJ2YWx1ZSI6ICJhIHZhbHVlIn0._3VgFmk3sRll_-von0EIC7ty32tcBEeZMc94Qr8htn8'
>>> jwt.verify_signed_token(b'secret', token)
(True, {'value': 'a value'})
"""
(header, payload, sig) = token.split('.')
hdata = header + '.' + payload
d = hmac.new(key, hdata.encode('utf-8'), 'sha256')
dig = d.digest()
denc = base64.urlsafe_b64encode(dig).decode().strip('=')
verified = hmac.compare_digest(sig, denc)
payload += '=' * (-len(payload) % 4)
payload_data = json.loads(base64.urlsafe_b64decode(payload).decode())
return (verified, payload_data)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment