JWT
ECDSA SHA-512 pyjwt
import jwt from cryptography.hazmat.primitives import serialization from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import ec private_key = ec.generate_private_key( ec.SECP384R1(), default_backend() ) data = b"this is some data I'd like to sign" signature = private_key.sign( data, ec.ECDSA(hashes.SHA256()) ) bytes_private_key = private_key.private_bytes( serialization.Encoding.PEM, serialization.PrivateFormat.PKCS8, serialization.NoEncryption()) bytes_public_key = private_key.public_key().public_bytes( serialization.Encoding.PEM, serialization.PublicFormat.SubjectPublicKeyInfo ) a = b'{private_key_data}' b = b'{public_key_data}' jwt_payload = {'iss': 'iss'} ejwt = jwt.encode(jwt_payload, a, algorithm='ES512').decode('utf-8') jwt.decode(ejwt, b, alogorithm='ES512')
View payload without verification
jwt.decode(jwt_token, verify=False) jwt.get_unverified_header(jwt_token)
# Other
openssl ec -in ecprivkey.pem -pubout -out ecpubkey.pem
import jwt # ssh-keygen -f ecdsa_key -e -m PKCS8 > ecdsa_key.pub private_key = open('ecdsa_key', 'r').read() public_key = open('ecdsa_key.pub', 'r').read() token = jwt.encode({ 'foo': 'bar' }, private_key, algorithm='ES256') print(jwt.decode(token, public_key, algorithms=['ES256']))
New
https://blog.miguelgrinberg.com/post/json-web-tokens-with-public-key-signatures
https://stackoverflow.com/questions/29650495/how-to-verify-a-jwt-using-python-pyjwt-with-public-key
Overview of Operation
https://www.iana.org/assignments/jwt/jwt.xhtml#claims
https://medium.com/vandium-software/5-easy-steps-to-understanding-json-web-tokens-jwt-1164c0adfcec
https://developer.okta.com/blog/2018/06/20/what-happens-if-your-jwt-is-stolen
https://medium.com/@darutk/understanding-id-token-5f83f50fa02e
RFC & Wiki
https://tools.ietf.org/html/rfc7519
https://en.wikipedia.org/wiki/JSON_Web_Token#Standard_fields
Usage
https://blog.miguelgrinberg.com/post/json-web-tokens-with-public-key-signatures
pip3 install pyjwt
JWT_SECRET = 'secret' encoded_jwt = jwt.encode({'some': 'payload'}, 'secret', algorithm='HS512') jwt.decode(encoded_jwt, 'secret')
Refresh Tokens
- https://flask-jwt-extended.readthedocs.io/en/latest/refresh_tokens.html
- https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/
Resources
- https://medium.com/vandium-software/5-easy-steps-to-understanding-json-web-tokens-jwt-1164c0adfcec
- https://developers.google.com/identity/toolkit/securetoken
- https://pyjwt.readthedocs.io/en/latest/usage.html
Storage
Store as a Secure Cookie in browser and not in storage path
Example
From https://developers.google.com/identity/toolkit/securetoken
{ "iss": "https://securetoken.google.com", "sub": "user_id" "aud": "project_id", "iat": issued_at, "exp": seconds_to_expiration, "email": "user_email" }
Using Flask and PyJWT:
@app.route("/example_endpoint") def example_endpoint(): access_token = flask.headers["Authorization"] try: user_data = jwt.decode(access_token, issuer="https://securetoken.google.com", audience="exemplary-example-123456") except jwt.InvalidTokenError: return 401 # Invalid token except jwt.ExpiredSignatureError: return 401 # Token has expired except jwt.InvalidIssuerError: return 401 # Token is not issued by Google except jwt.InvalidAudienceError: return 401 # Token is not valid for this endpoint user_id = user_data["sub"] data = get_some_data_by_user_id(user_id) return json.dumps(data)
ssh-keygen -t rsa -b 4096 -m PEM -f jwtRS256.key # Don't use passphrase openssl rsa -in jwtRS256.key -pubout -outform PEM -out jwtRS256.key.pub cat jwtRS256.key cat jwtRS256.key.pub