Activity 46: Documentation of Python JWT
Introduction to JWT
What is JWT?
JSON Web Token (JWT) is a secure way to transmit information between parties as a JSON object, which is digitally signed to ensure data integrity and authenticity.How JWT Works
JWTs are often used in authentication and authorization systems. When a user logs in, the server creates a token containing essential user information, signed with a secret key. The user then uses this token to authenticate and access protected resources, allowing for stateless and efficient authentication.Why JWT is Important
JWTs make applications more scalable by handling authentication without storing session data on the server. They also provide better security through token expiration, ensuring that unauthorized users cannot access protected resources.
Step-by-Step Guide for Implementing JWT in Python Flask
Step 1: Set Up the Project Directory
Open Command Prompt and create a new directory for the project:
mkdir nicolas_python_flask_jwt cd nicolas_python_flask_jwt
Create a Virtual Environment:
python -m venv env
Activate the Virtual Environment (on Windows):
.\env\Scripts\activate
Step 2: Install Flask and PyJWT Libraries
With the virtual environment active, install Flask and PyJWT (a popular Python library for working with JWTs):
pip install Flask PyJWT
Step 3: Create the app.py
File
In the project folder, create a new file named app.py
where we’ll add the Flask routes and JWT logic.
Import Libraries: We’ll need
Flask
,request
,jsonify
from Flask, andjwt
for generating and verifying tokens.Create the Flask App:
from flask import Flask, request, jsonify import jwt import datetime app = Flask(__name__) app.config['SECRET_KEY'] = 'your_secret_key' # Replace with a strong secret key
The
SECRET_KEY
is crucial for encoding and decoding JWTs securely. Replace'your_secret_key'
with a unique, strong key.
Step 4: Implement the JWT Routes
Now, I’ll add the main endpoints for /register
, /login
, /get-jwt
, and /set-jwt
.
4.1 POST /register
Route
The /register
endpoint allows users to create an account. For simplicity, I’ll store user data in memory.
users = {} # A dictionary to store user data temporarily
@app.route('/register', methods=['POST'])
def register():
data = request.json
username = data.get('username')
password = data.get('password')
if username in users:
return jsonify({"message": "User already exists"}), 400
users[username] = password
return jsonify({"message": "User registered successfully"}), 201
4.2 POST /login
Route
The /login
endpoint authenticates the user and generates a JWT if the credentials are valid.
@app.route('/login', methods=['POST'])
def login():
data = request.json
username = data.get('username')
password = data.get('password')
if users.get(username) != password:
return jsonify({"message": "Invalid username or password"}), 401
token = jwt.encode({
'username': username,
'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=30)
}, app.config['SECRET_KEY'], algorithm="HS256")
return jsonify({"token": token})
This endpoint generates a JWT token with an expiration time of 30 minutes, encoded with the user’s username and our secret key.
4.3 GET /get-jwt
Route
The /get-jwt
route allows us to verify the token. If the token is valid, the server responds with the user’s information.
@app.route('/get-jwt', methods=['GET'])
def get_jwt():
token = request.headers.get('Authorization')
if not token:
return jsonify({"message": "Token is missing!"}), 401
try:
data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=["HS256"])
return jsonify({"user": data['username']})
except jwt.ExpiredSignatureError:
return jsonify({"message": "Token has expired!"}), 401
except jwt.InvalidTokenError:
return jsonify({"message": "Invalid token!"}), 401
4.4 POST /set-jwt
Route
In this route, I’ll create a new token and return it. This endpoint can be used for generating tokens for other services or sessions.
@app.route('/set-jwt', methods=['POST'])
def set_jwt():
data = request.json
username = data.get('username')
if username not in users:
return jsonify({"message": "User does not exist"}), 404
token = jwt.encode({
'username': username,
'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=30)
}, app.config['SECRET_KEY'], algorithm="HS256")
return jsonify({"token": token})
Step 5: Run the Flask Application
To start the server, use the command:
python app.py
This will run the app on http://127.0.0.1:5000/
Step 6: Test the Endpoints
Using Postman or any other tool, test each endpoint:
POST
/register
:Set the request type to POST and the URL to
http://127.0.0.1:5000/register
.In the Body, select raw and JSON format, then enter a JSON object with
"username"
and"password"
fields.If the user already exists, the response will be:
POST
/login
:Send a POST request to
http://127.0.0.1:5000/login
with the same JSON structure as the/register
endpoint.The response should contain a JWT token if the credentials are correct.
If the credentials are incorrect, you’ll see:
GET
/get-jwt
:Copy the token from the
/login
response.Send a GET request to
http://127.0.0.1:5000/get-jwt
with the token in the Authorization header.The server should return the username if the token is valid.
POST
/set-jwt
:Send a POST request to
http://127.0.0.1:5000/set-jwt
with"username"
in the JSON body.This will return a new JWT for the specified username.
If the username does not exist, you’ll receive:
Step 7: Push the Project to GitHub
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/MonetForProgrammingPurposes/cd-nicolas_python_flask_encryption_and_decryption.git
git push -u origin master