Skip to content
geeksforgeeks
  • Tutorials
    • Python
    • Java
    • Data Structures & Algorithms
    • ML & Data Science
    • Interview Corner
    • Programming Languages
    • Web Development
    • CS Subjects
    • DevOps And Linux
    • School Learning
    • Practice Coding Problems
  • Courses
    • DSA to Development
    • Get IBM Certification
    • Newly Launched!
      • Master Django Framework
      • Become AWS Certified
    • For Working Professionals
      • Interview 101: DSA & System Design
      • Data Science Training Program
      • JAVA Backend Development (Live)
      • DevOps Engineering (LIVE)
      • Data Structures & Algorithms in Python
    • For Students
      • Placement Preparation Course
      • Data Science (Live)
      • Data Structure & Algorithm-Self Paced (C++/JAVA)
      • Master Competitive Programming (Live)
      • Full Stack Development with React & Node JS (Live)
    • Full Stack Development
    • Data Science Program
    • All Courses
  • Flask Templates
  • Jinja2
  • Flask-REST API
  • Python SQLAlchemy
  • Flask Bcrypt
  • Flask Cookies
  • Json
  • Postman
  • Django
  • Flask Projects
  • Flask Interview Questions
  • MongoDB
  • Python MongoDB
  • Python Database
  • ReactJs
  • Vue.Js
Open In App
Next Article:
Using JWT for user authentication in Flask
Next article icon

Using JWT for user authentication in Flask

Last Updated : 28 Mar, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

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-

JWT-fs
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:

  • Flask initializes the web application.
  • SECRET_KEY is used to sign JWT tokens.
  • SQLALCHEMY_DATABASE_URI specifies the SQLite database.
  • SQLAlchemy is set up for database interactions.

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:

  • id is the primary key.
  • public_id stores a unique identifier for each user.
  • name, email, and password store user details.

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:

  • '/register' route stores user details securely with hashed passwords.
  • '/login' route checks credentials and generates a JWT token.
  • The token is stored in cookies and used for authentication.

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:

  • Retrieves the token from cookies.
  • Decodes and verifies the token.
  • Fetches the corresponding user from the database.
  • Returns an error message if the token is missing or invalid.

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:

  • The home route renders the login page.
  • The dashboard route is protected with JWT and displays the logged-in user's name.

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:

  • db.create_all() - ensures the database is created before running the server.
  • app.run(debug=True) - runs the Flask application in debug mode.

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

  • Open Postman and send a POST request to http://127.0.0.1:5000/signup.
  • Provide name, email, and password in the body (x-www-form-urlencoded).
  • If successful, it redirects to the login page.
JWT-post1
Registeration

3. Login to get JWT Token

  • Send a POST request to http://127.0.0.1:5000/login.
  • Provide the registered email and password.
  • If successful, a JWT token is set in cookies.
JWT-post2-1
Login

4. Test Unauthorized Access

  • Open Postman and send a GET request to http://127.0.0.1:5000/dashboard without a token.
  • You should receive a 401 Unauthorized error.
JWT-post2
Unauthorized access

Next Article
Using JWT for user authentication in Flask

D

debdutgoswami
Improve
Article Tags :
  • Python
  • Web Technologies
  • Python Flask
Practice Tags :
  • python

Similar Reads

    Mastering JWT authentication in Express
    While creating any application it is very important to add authentication to ensure that only authorized users can access the protected resources. A JSON Web Token (JWT) is a JSON object utilized to securely transmit information between two parties over the web. Primarily employed in authentication
    4 min read
    Flask API Authentication with JSON Web Tokens
    Authentication is the process of verifying the identity of the user. It checks whether the user is real or not. It is used to provide access to resources only to valid users. There are two types of Authentication: Single Factor Authentication: In this only one piece of information is needed to verif
    7 min read
    Authentication using Python requests
    Authentication refers to giving a user permissions to access a particular resource. Since, everyone can't be allowed to access data from every URL, one would require authentication primarily. To achieve this authentication, typically one provides authentication data through Authorization header or a
    2 min read
    How to Add Authentication to App with Flask-Login
    We can implement authentication, login/logout functionality in flask app using Flask-Login. In this article, we'll explore how to add authentication to a Flask app using Flask-Login.To get started, install Flask, Flask-Login, Flask-SQLAlchemy and Werkzeug using this command:pip install flask flask_s
    6 min read
    How To Use Web Forms in a Flask Application
    A web framework called Flask provides modules for making straightforward web applications in Python. It was created using the WSGI tools and the Jinja2 template engine. An example of a micro-framework is Flask. Python web application development follows the WSGI standard, also referred to as web ser
    5 min read
geeksforgeeks-footer-logo
Corporate & Communications Address:
A-143, 7th Floor, Sovereign Corporate Tower, Sector- 136, Noida, Uttar Pradesh (201305)
Registered Address:
K 061, Tower K, Gulshan Vivante Apartment, Sector 137, Noida, Gautam Buddh Nagar, Uttar Pradesh, 201305
GFG App on Play Store GFG App on App Store
Advertise with us
  • Company
  • About Us
  • Legal
  • Privacy Policy
  • In Media
  • Contact Us
  • Advertise with us
  • GFG Corporate Solution
  • Placement Training Program
  • Languages
  • Python
  • Java
  • C++
  • PHP
  • GoLang
  • SQL
  • R Language
  • Android Tutorial
  • Tutorials Archive
  • DSA
  • Data Structures
  • Algorithms
  • DSA for Beginners
  • Basic DSA Problems
  • DSA Roadmap
  • Top 100 DSA Interview Problems
  • DSA Roadmap by Sandeep Jain
  • All Cheat Sheets
  • Data Science & ML
  • Data Science With Python
  • Data Science For Beginner
  • Machine Learning
  • ML Maths
  • Data Visualisation
  • Pandas
  • NumPy
  • NLP
  • Deep Learning
  • Web Technologies
  • HTML
  • CSS
  • JavaScript
  • TypeScript
  • ReactJS
  • NextJS
  • Bootstrap
  • Web Design
  • Python Tutorial
  • Python Programming Examples
  • Python Projects
  • Python Tkinter
  • Python Web Scraping
  • OpenCV Tutorial
  • Python Interview Question
  • Django
  • Computer Science
  • Operating Systems
  • Computer Network
  • Database Management System
  • Software Engineering
  • Digital Logic Design
  • Engineering Maths
  • Software Development
  • Software Testing
  • DevOps
  • Git
  • Linux
  • AWS
  • Docker
  • Kubernetes
  • Azure
  • GCP
  • DevOps Roadmap
  • System Design
  • High Level Design
  • Low Level Design
  • UML Diagrams
  • Interview Guide
  • Design Patterns
  • OOAD
  • System Design Bootcamp
  • Interview Questions
  • Inteview Preparation
  • Competitive Programming
  • Top DS or Algo for CP
  • Company-Wise Recruitment Process
  • Company-Wise Preparation
  • Aptitude Preparation
  • Puzzles
  • School Subjects
  • Mathematics
  • Physics
  • Chemistry
  • Biology
  • Social Science
  • English Grammar
  • Commerce
  • World GK
  • GeeksforGeeks Videos
  • DSA
  • Python
  • Java
  • C++
  • Web Development
  • Data Science
  • CS Subjects
@GeeksforGeeks, Sanchhaya Education Private Limited, All rights reserved
We use cookies to ensure you have the best browsing experience on our website. By using our site, you acknowledge that you have read and understood our Cookie Policy & Privacy Policy
Lightbox
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
geeksforgeeks-suggest-icon
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.
geeksforgeeks-improvement-icon
Suggest Changes
min 4 words, max Words Limit:1000

Thank You!

Your suggestions are valuable to us.

What kind of Experience do you want to share?

Interview Experiences
Admission Experiences
Career Journeys
Work Experiences
Campus Experiences
Competitive Exam Experiences