Documentation of Activity#45
Step-by-Step Guide for Implementing JWT in Python Flask
Step 1: Create Folder
2. Create a Virtual Environment (Optional but Recommended)
It's a good practice to use a virtual environment to isolate your dependencies. You can create and activate a virtual environment using the following commands in your CMD:
python -m venv venv
venv\Scripts\activate
After activation, your terminal prompt should change to indicate the virtual environment is active.
3. Install Required Libraries
Install Flask, PyJWT, and Werkzeug (for password hashing). These libraries are essential for the Flask API and JWT implementation.
pip install Flask PyJWT werkzeug
Flask: The micro web framework.
PyJWT: A library for working with JSON Web Tokens.
Werkzeug: A utility library, which will be used to hash and check passwords securely.
Step 4: 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:
Flask App Code:
from flask import Flask, jsonify, request import jwt import datetime from werkzeug.security import generate_password_hash, check_password_hash app = Flask(__name__) # Secret key for encoding and decoding JWT SECRET_KEY = 'your_secret_key' # In-memory "database" for users (for demonstration purposes) users_db = {} # Helper function to create a JWT def create_jwt(user_id): expiration_time = datetime.datetime.utcnow() + datetime.timedelta(hours=1) payload = { 'sub': user_id, # Subject claim (username) 'exp': expiration_time } token = jwt.encode(payload, SECRET_KEY, algorithm='HS256') return token # Route to get a JWT (For demonstration, will just return a pre-generated token) @app.route('/get-jwt', methods=['GET']) def get_jwt(): token = request.headers.get('Authorization') # Expecting JWT in the Authorization header if token: try: # Decode JWT to verify its validity decoded_token = jwt.decode(token, SECRET_KEY, algorithms=['HS256']) return jsonify({"message": "Token is valid", "user": decoded_token['sub']}), 200 except jwt.ExpiredSignatureError: return jsonify({"error": "Token has expired"}), 401 except jwt.InvalidTokenError: return jsonify({"error": "Invalid token"}), 401 return jsonify({"error": "Token is missing"}), 400 # Route to set a JWT (Login or create JWT by providing username and password) @app.route('/set-jwt', methods=['POST']) def set_jwt(): data = request.get_json() username = data.get('username') password = data.get('password') if username not in users_db: return jsonify({"error": "User not found"}), 404 user = users_db[username] if not check_password_hash(user['password'], password): return jsonify({"error": "Invalid password"}), 401 # Create JWT token token = create_jwt(username) return jsonify({"message": "JWT created", "token": token}), 200 # Route to handle user login @app.route('/login', methods=['POST']) def login(): data = request.get_json() username = data.get('username') password = data.get('password') if username not in users_db: return jsonify({"error": "User not found"}), 404 user = users_db[username] if not check_password_hash(user['password'], password): return jsonify({"error": "Invalid password"}), 401 # Create JWT token on successful login token = create_jwt(username) return jsonify({"message": "Login successful", "token": token}), 200 # Route to handle user registration @app.route('/register', methods=['POST']) def register(): data = request.get_json() username = data.get('username') password = data.get('password') if username in users_db: return jsonify({"error": "Username already exists"}), 400 # Hash the password before storing hashed_password = generate_password_hash(password) users_db[username] = {'password': hashed_password} return jsonify({"message": "User registered successfully"}), 201 if __name__ == '__main__': app.run(debug=True)
Running the Flask App:
To start the Flask app, run the following command in your terminal:
python app.py
Make sure your Flask app is running at http://localhost:5000
. You can then test the endpoints using Postman as described above.
Explanation of Routes:
GET /get-jwt
:- This route checks if the provided JWT in the
Authorization
header is valid. If valid, it returns a success message along with the decoded user info (username). If not, it returns an error.
- This route checks if the provided JWT in the
POST /set-jwt
:- This route receives a
username
andpassword
and returns a JWT if the credentials are correct.
- This route receives a
POST /login
:- This route handles login. If the username and password are correct, it returns a JWT.
POST /register
:- This route allows new users to register by providing a
username
andpassword
. The password is hashed and stored in theusers_db
.
- This route allows new users to register by providing a
How to Test Using Postman
Register a New User (POST /register):
Method:
POST
Body (JSON format):
{
"username": "Lucy",
"password": "mypassword"
}
Response (if successful):
{
"message": "User registered successfully"
}
Login and Get JWT (POST /login):
Method:
POST
Body (JSON format):
{ "username": "Lucy", "password": "mypassword" }
Response (if successful):
{ "message": "Login successful", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJMdWN5IiwiZXhwIjoxNzMxNDg2NDk1fQ.Ee3Gmb7n3veTz5y6ApaQv-MP_rLnjJvpfY4oTvPZl6s" }
Access Protected Route with JWT (GET /get-jwt):
Method:
GET
In Postman:
Go to the Headers tab.
Add a key
Authorization
with the valueBearer your_jwt_token_here
.
Response (if the token is valid):
{ "message": "Token is valid", "user": "Lucy" }
Access Protected Route Without JWT or Invalid JWT:
If you don't provide the JWT or use an expired/invalid JWT, you will receive an error message:
{ "error": "Token is missing" }
or:
{ "error": "Invalid token" }