Last active
April 13, 2022 21:24
-
-
Save darelf/190bc97b29e91509534d7535ebde4762 to your computer and use it in GitHub Desktop.
Python 3 JWT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
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