Introduction to PyJWT
PyJWT is a Python library that allows developers to encode and decode JSON Web Tokens (JWT) easily and securely. This versatile library is indispensable for building authentication systems, secure APIs, and managing session tokens. In this guide, we will cover the essentials of PyJWT, delve into its APIs, and finish with a complete app example.
What is a JSON Web Token (JWT)?
JWT is an open standard (RFC 7519) that defines a compact way for securely transmitting information between parties as a JSON object. The information can be verified and trusted because it is digitally signed using a secret (HMAC algorithm) or a public/private key pair (RSA or ECDSA).
Installing PyJWT
To get started, install PyJWT via pip:
pip install pyjwt
Encoding and Decoding JWTs
At the heart of PyJWT is its ability to encode and decode tokens. Here’s how you can use the library’s APIs:
Encoding a JWT
Use the jwt.encode()
method to create a token:
import jwt import datetime payload = { "user_id": 123, "role": "admin", "exp": datetime.datetime.utcnow() + datetime.timedelta(hours=1) } secret = "your-256-bit-secret" token = jwt.encode(payload, secret, algorithm="HS256") print(token)
Decoding a JWT
To verify and decode a token, use the jwt.decode()
method:
decoded_data = jwt.decode(token, secret, algorithms=["HS256"]) print(decoded_data)
This will return the original payload if the token is valid and hasn’t expired.
Handling Expired Tokens
PyJWT raises the jwt.ExpiredSignatureError
exception if a token is expired. Always wrap decoding in a try-except block:
try: decoded_data = jwt.decode(token, secret, algorithms=["HS256"]) except jwt.ExpiredSignatureError: print("Token has expired")
Creating a Token with Additional Headers
Custom headers can be added during token creation:
headers = {"kid": "key-id-example"} token_with_headers = jwt.encode(payload, secret, algorithm="HS256", headers=headers) print(token_with_headers)
Algorithms Supported by PyJWT
PyJWT supports multiple algorithms, including HS256, RS256, and ES256. For asymmetrical encryption like RSA, supply the private key during encoding:
private_key = """-----BEGIN PRIVATE KEY----- YOUR-RSA-PRIVATE-KEY -----END PRIVATE KEY-----""" public_key = """-----BEGIN PUBLIC KEY----- YOUR-RSA-PUBLIC-KEY -----END PUBLIC KEY-----""" token = jwt.encode(payload, private_key, algorithm="RS256") decoded_data = jwt.decode(token, public_key, algorithms=["RS256"]) print(decoded_data)
Complete Example: A Flask API Secured by PyJWT
Here’s a mini web application using Flask and PyJWT for authentication:
from flask import Flask, request, jsonify import jwt import datetime app = Flask(__name__) secret = "your-256-bit-secret" @app.route("/login", methods=["POST"]) def login(): username = request.json.get("username") password = request.json.get("password") # Dummy check; replace with real user validation if username == "admin" and password == "password": payload = { "username": username, "exp": datetime.datetime.utcnow() + datetime.timedelta(hours=1) } token = jwt.encode(payload, secret, algorithm="HS256") return jsonify({"token": token}) return jsonify({"message": "Invalid credentials"}), 401 @app.route("/protected", methods=["GET"]) def protected(): token = request.headers.get("Authorization", "").split(" ")[-1] try: decoded = jwt.decode(token, secret, algorithms=["HS256"]) return jsonify({"message": f"Hello, {decoded['username']}!"}) except jwt.ExpiredSignatureError: return jsonify({"message": "Token expired"}), 401 except jwt.InvalidTokenError: return jsonify({"message": "Invalid token"}), 401 if __name__ == "__main__": app.run(debug=True)
In this example, users can log in to receive a token and use that token to access protected routes. The app demonstrates token creation, decoding, and error handling.
Conclusion
PyJWT is a lightweight and straightforward library that simplifies the process of handling JSON Web Tokens in Python applications. Whether you are building a web app, an API, or a distributed system, PyJWT is a great tool for managing secure tokens. Start using PyJWT today to secure your applications efficiently!