Activity 46: Documentation of Python JWT

Step 1: Create a folder

  • name of the folder; “python-flask-jwt

Step 2: Open the folder and launch on “cmd or terminal

Step 3: Create a virtual environment

  • use the command below to create a virtual environment:
python -m venv venv

The command python -m venv venv creates a new virtual environment in a folder named "venv" inside your project directory. This environment will have its own Python interpreter and libraries.

Verify the venv folder in the project folder which is named “python-flask-encryption-decryption

Step 4: Activate the python virtual environment

  • use the command below to activate python virtual environment
venv\Scripts\activate

Once activated, the terminal prompt changes to show the name of the environment (in this case, (venv)), indicating that you are now working within the virtual environment.

Step 4: Install Flask

  • use the command below to install flask
pip install Flask

Step 5: Add venv on gitignore

Adding the venv directory to .gitignore is essential to prevent the virtual environment files from being tracked by version control tools like Git. Since the venv directory contains environment-specific files that are not necessary for the application’s source code, it is a good practice to exclude it from version control to keep the repository clean and reduce clutter.

Steps to add venv to .gitignore, use the command below**:**

nul > .gitignore

Open the .gitignore file with a text editor or notepad.

  1. Add the following line below:

        venv/
    

save the file;

Step 6: Open the project in pycharm

Step 7: Create a directory folder and name it “templates

Step 8: Inside the templates directory/folder, create a index.html

Step 9: Create a python file named “app.py"

Step 10: In the “app.py", import Flask and render_template

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def hello_world():
    return render_template('index.html', message="Hello, World!")

if __name__ == '__main__':
    app.run(debug=True)

Step 11: In the “index.html” file, use the passed variable:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello Page</title>
</head>
<body>
    <h1>{{ message }}</h1>
</body>
</html>

In this example, the string "Hello, World!" is passed as a variable (message) from the Python script to the HTML template. The template renders the variable inside the HTML content.

Step 12: Install PyJWT

To implement JWT (JSON Web Token) authentication in Python, we can use the PyJWT library, which simplifies the process of creating and verifying JWT tokens.

Step-by-Step Guide:

  1. Install the PyJWT library: First, install the PyJWT package using pip:
pip install PyJWT
  • on pycharm terminal or cmd

  1. Create and Verify JWT in Python: Below is an example of how you can generate and verify JWT tokens in Python.

Step 13: Create .env file

  • commit .env on pycharm

click more tools:

click commit:

but before that, to use “.env" make sure to install dotenv on terminal by using this command below:

python.exe -m pip install --upgrade pip
  • to upgrade to the latest version of the dotenv

  • commit changes in “.env" file

  • check the .env

  • add “chore: python flask jwt” in the message then commit

Step 14: Add secret key in the “.env" file

  • using this code:
JWT_SECRET_KEY="superjwtsecret"

Step 15: Import JWT on ”app.py"


# Function to generate a JWT
def create_jwt(user_id):
# Define the token payload
payload = {
"user_id": user_id,
"exp": datetime.datetime.utcnow() + datetime. timedelta(minutes=30), #
"iat": datetime.datetime.utcnow(), # Issued at
"sub": "authentication"

# Encode the payload to create the token
token = jwt.encode(payload, SECRET_KEY, algorithm="HS256")

return token

Step 16: Create route for get, set, login, and register

in “app.py” i have imported the bcrypt, jwt and the other python file named “jwt_try

the code below indicates the functionalities of the route in postman which is the POST and GET method

import bcrypt
import jwt
from flask import Flask, render_template, request, jsonify, make_response

import jwt_try

app = Flask(__name__)

@app.route('/')
def hello_world():
    return render_template('index.html', message="Hello, World!")

@app.route('/setcookie', methods=['POST'])
def set_cookie():
    # get name from request
    name = request.json.get('name')
    resp = make_response(jsonify({"message": "cookie has been set"}))
    resp.set_cookie('name', name, max_age=60*60*24) # cookie last for 1 day
    return resp

@app.route('/getcookie', methods=['GET'])
def get_cookie():
    # get name from request
    name = request.cookies.get('name')
    if name:
        return jsonify({"name": name})
    else:
        return jsonify({"message": "no name cookie found"}), 404

@app.route('/hash', methods=['POST'])
def hash_password():
    password = request.json.get('password')
    hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
    return jsonify({"hashed_password": hashed_password.decode('utf-8')})

@app.route('/verify', methods=['POST'])
def verify_password():
    password = request.json.get('password')
    hashed_password = request.json.get('hashed_password')
    is_verified = bcrypt.checkpw(password.encode('utf-8'), hashed_password.encode('utf-8'))
    return jsonify({"verified": is_verified})


@app.route('/login', methods=['POST'])
def login_user():
    data = request.get_json()
    if data.username == 'admin' and data.password == 'admin':
        token = jwt_try.generate_token(data)
        return jsonify({"token": token})
    else:
        return jsonify({"message": "Invalid credentials"}), 401

@app.route('/getuser', methods=['GET'])
def get_user():
    token = request.headers.get('authorization')
    if not token:
        return jsonify({"message": "token is missing"}), 401
    try:
        payload = jwt_try.verify_token(token)
        return jsonify({"user": payload})
    except jwt.ExpiredSignatureError:
        return jsonify({"message": "token has expired"}), 401
    except jwt.InvalidTokenError:
        return jsonify({"message": "Invalid token"}), 401

if __name__ == '__main__':
    app.run(debug=True)

on the other python file named “jwt_try”, this is the code inside it for the generated token and payload


import os
import jwt

# Function to generate a JWT
def generate_token(data):
    # Define the token payload
    payload = {
        "user_id": data.get("user_id"),
        "role": data.get("role"),
        "sub": "authentication"
    }

    # Encode the payload to create the token
    token = jwt.encode(payload, os.getenv("JWT_SECRET_KEY", ""), algorithm="HS256")
    return token


data = {
    "user_id": 1,
    "role": "admin"
}

token = generate_token(data)
print(token)


def verify_token(token):
    # decode the token to get the payload
    try:
        payload = jwt.decode(token, os.getenv("JWT_SECRET_KEY", ""), algorithms=["HS256"])
        return payload
    except jwt.ExpiredSignatureError:
        return "Token has expired!"
    except jwt.InvalidTokenError:
        return "Invalid Token!"


payload = verify_token(token)
print(payload)

GitHub Repository link: https://github.com/FranciscoJohannes/francisco_python_flask_jwt