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