A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://www.geeksforgeeks.org/using-jwt-for-user-authentication-in-flask/ below:

Using JWT for user authentication in Flask

Using JWT for user authentication in Flask

Last Updated : 15 Jul, 2025

JWT (JSON Web Token) is a compact, secure, and self-contained token used for securely transmitting information between parties. It is often used for authentication and authorization in web applications.

A JWT consists of three parts:

  1. Header - Contains metadata (e.g., algorithm used for signing).
  2. Payload - Stores user information (claims like user ID, roles).
  3. Signature - Ensures token integrity using a secret key.

In Flask, JWT is commonly used to authenticate users by issuing tokens upon login and verifying them for protected routes. Let's see how to create a basic flask app that uses JWT tokens for authentication.

Installation and Setting Up Flask

Create a project folder and then inside that folder create and activate a virtual environment to install flask and other necessary modules in it. Use these commands to create and activate a new virtual environment-

python -m venv venv
.venv\Scripts\activate

And after that install flask and other relevant libraries using this command-

pip install Flask Flask-SQLAlchemy Werkzeug PyJWT

Create a "templates" folder, it will contain all the html files for the app.

To know more about creating flask apps, refer to- Creating Flask Applicaions

File Structure

After completing the project and running the app for atleast once so that the databse is created, our file system should look similar to this-

Files Structure Creating app.py

Let's build our app step by step to implement authentication using JWT tokens. We'll also create an unprotected route to show that without a valid JWT, access is not restricted.

App Configuration

Before we start implementing authentication, let's set up our Flask application and configure necessary settings.

Python
from flask import Flask, render_template, request, redirect, url_for, jsonify, make_response
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
import jwt
import uuid
from datetime import datetime, timezone, timedelta
from functools import wraps

app = Flask(__name__)

# Configuration
app.config['SECRET_KEY'] = 'your_secret_key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///Database.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

# Database setup
db = SQLAlchemy(app)

Explanation:

Creating the User Model

We need a database model to store user details. For this app, we are going to use SQLAlchemy for our database. Here's how to create it.

Python
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    public_id = db.Column(db.String(50), unique=True)
    name = db.Column(db.String(100))
    email = db.Column(db.String(70), unique=True)
    password = db.Column(db.String(80))

Explanation:

Implementing Authentication (Login and Registration)

This section covers user authentication, including login and signup features.

Python
@app.route('/signup', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        name = request.form['name']
        email = request.form['email']
        password = request.form['password']

        existing_user = User.query.filter_by(email=email).first()
        if existing_user:
            return jsonify({'message': 'User already exists. Please login.'}), 400

        hashed_password = generate_password_hash(password)
        new_user = User(public_id=str(uuid.uuid4()), name=name, email=email, password=hashed_password)

        db.session.add(new_user)
        db.session.commit()

        return redirect(url_for('login'))

    return render_template('register.html')

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        email = request.form['email']
        password = request.form['password']
        user = User.query.filter_by(email=email).first()

        if not user or not check_password_hash(user.password, password):
            return jsonify({'message': 'Invalid email or password'}), 401

        token = jwt.encode({'public_id': user.public_id, 'exp': datetime.now(timezone.utc) + timedelta(hours=1)},
                           app.config['SECRET_KEY'], algorithm="HS256")

        response = make_response(redirect(url_for('dashboard')))
        response.set_cookie('jwt_token', token)

        return response

    return render_template('login.html')

Explanation:

Implementing JWT Token Verification

To secure routes, we create a decorator that checks for a valid JWT token.

Python
def token_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        token = request.cookies.get('jwt_token')

        if not token:
            return jsonify({'message': 'Token is missing!'}), 401

        try:
            data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=["HS256"])
            current_user = User.query.filter_by(public_id=data['public_id']).first()
        except:
            return jsonify({'message': 'Token is invalid!'}), 401

        return f(current_user, *args, **kwargs)

    return decorated

Explanation:

Creating Routes for Home and Dashboar

These routes handle rendering pages and displaying user information after login.

Python
@app.route('/')
def home():
    return render_template('login.html')

@app.route('/dashboard')
@token_required
def dashboard(current_user):
    return f"Welcome {current_user.name}! You are logged in."

Explanation:

Running the Application

Finally, we initialize the database and start the Flask server.

Python
if __name__ == '__main__':
    with app.app_context():
        db.create_all()
    app.run(debug=True)

Explanation:

Complete app.py code Python
from flask import Flask, render_template, request, redirect, url_for, jsonify, make_response
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
import jwt
import uuid
from datetime import datetime, timezone, timedelta
from functools import wraps

app = Flask(__name__)

# Configuration
app.config['SECRET_KEY'] = 'your_secret_key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///Database.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

# Database setup
db = SQLAlchemy(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    public_id = db.Column(db.String(50), unique=True)
    name = db.Column(db.String(100))
    email = db.Column(db.String(70), unique=True)
    password = db.Column(db.String(80))

# Token required decorator
def token_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        token = request.cookies.get('jwt_token')

        if not token:
            return jsonify({'message': 'Token is missing!'}), 401

        try:
            data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=["HS256"])
            current_user = User.query.filter_by(public_id=data['public_id']).first()
        except:
            return jsonify({'message': 'Token is invalid!'}), 401

        return f(current_user, *args, **kwargs)

    return decorated

@app.route('/')
def home():
    return render_template('login.html')

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        email = request.form['email']
        password = request.form['password']
        user = User.query.filter_by(email=email).first()

        if not user or not check_password_hash(user.password, password):
            return jsonify({'message': 'Invalid email or password'}), 401

        token = jwt.encode({'public_id': user.public_id, 'exp': datetime.now(timezone.utc) + timedelta(hours=1)}, 
                           app.config['SECRET_KEY'], algorithm="HS256")

        response = make_response(redirect(url_for('dashboard')))
        response.set_cookie('jwt_token', token)

        return response

    return render_template('login.html')

@app.route('/signup', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        name = request.form['name']
        email = request.form['email']
        password = request.form['password']

        existing_user = User.query.filter_by(email=email).first()
        if existing_user:
            return jsonify({'message': 'User already exists. Please login.'}), 400

        hashed_password = generate_password_hash(password)
        new_user = User(public_id=str(uuid.uuid4()), name=name, email=email, password=hashed_password)

        db.session.add(new_user)
        db.session.commit()

        return redirect(url_for('login'))

    return render_template('register.html')

@app.route('/dashboard')
@token_required
def dashboard(current_user):
    return f"Welcome {current_user.name}! You are logged in."

if __name__ == '__main__':
    with app.app_context():
        db.create_all()
    app.run(debug=True)
Creating Templates

Inside the templates folder create two files login.html file and register.html, these files will serve the page for registration and login, below is the code for these file-

login.html HTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login</title>
</head>
<body>
    <h2>Login</h2>
    <form action="/login" method="POST">
        <label>Email:</label>
        <input type="email" name="email" required>
        <br>
        <label>Password:</label>
        <input type="password" name="password" required>
        <br>
        <button type="submit">Login</button>
    </form>
    <p>Don't have an account? <a href="{{ url_for('register') }}">Register here</a></p>
</body>
</html>
register.html HTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Register</title>
</head>
<body>
    <h2>Signup</h2>
    <form action="/signup" method="POST">
        <label>Name:</label>
        <input type="text" name="name" required>
        <br>
        <label>Email:</label>
        <input type="email" name="email" required>
        <br>
        <label>Password:</label>
        <input type="password" name="password" required>
        <br>
        <button type="submit">Signup</button>
    </form>
    <p>Already have an account? <a href="{{ url_for('login') }}">Login here</a></p>
</body>
</html>
Running and Testing Application

After setting up everything, let's test the JWT authentication using Postman. Make sure that Postman is installed on your system, download and install it from here if it isn't.

To test the application follow these steps-

1. Start the Flask app using the following command in terminal

python app.py

2. Register a new user

Registeration

3. Login to get JWT Token

Login

4. Test Unauthorized Access

Unauthorized access

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4