Quick Summary
Flask JWT Authentication enables secure user authentication through tokens in Flask applications. This blog provides a step-by-step guide to implementing JWT Authentication in Flask. It covers essential topics, including the Flask framework, REST APIs, and Auth Token Authentication. Designed for beginners, the tutorial simplifies complex concepts and breaks them into clear, manageable sections for easy understanding.
JSON Web Tokens (JWTs) are a compact and secure way to transmit information as a JSON object, commonly used for authentication and secure data exchange. A JWT has three components:
JWTs are particularly useful in stateless authentication, where the server doesn’t store session data. Instead, the client sends the JWT with each request, enabling the server to authenticate and authorize efficiently. They are lightweight, self-contained, and ideal for securing REST APIs.
Flask is a lightweight, flexible, and easy-to-use web framework for Python. It is designed to help developers build web applications quickly and with minimal overhead. Flask is often referred to as a “microframework” because it provides the essential tools for web development without enforcing a specific project structure or including unnecessary features. The comprehensive features of Flask include:
Flask is widely used for small to medium-sized projects and serves as a solid foundation for more complex applications with the addition of extensions. Its simplicity and flexibility make it a popular choice among developers.
This tutorial provides a step-by-step guide to implementing JWT (JSON Web Token) authentication in a Flask application. Here, you will explore how to secure API endpoints, authenticate users, and manage authorization efficiently. You’ll have a solid foundation for building a secure authentication system by the end.
Let’s start with the implementation of the Flask JWT Authentication.
Here’s my system setup and JWT Flask Authentication example for better understanding:
A virtual environment ensures that none of the packages used in the project conflict with system packages. It is also a good practice to avoid polluting your OS by installing every package directly onto the OS.
We will use the virtualenv command for setting up a new virtual environment in our project.
To proceed, we will need a pip command. If you don’t have pip installed on your system, use the below command to install it.
Once you have the pip command installed on your system, run the following command to install virtualenv.
Now, run the mkdir command to create a new folder/directory for storing the virtual environment.
To change the current working directory to myflaskproject run the following command:
Inside the myflaskproject directory, create a new virtual environment with the help of the virtualenv tool:
After you have successfully created a virtual environment using the virtualenv tool, activate the virtual environment using the following command:
Now, it’s time to install the packages we need for this project to build Python REST API authentication token and other necessary packages for this API project such as-
An efficient way to do this is to create a requirements.txt file and list all the packages in it. You can also declare the packages’ versions wherever necessary.
For example, create one ‘requirement.txt’ file and paste the following packages into requirements.txt :
Now, use the following command to install all the listed packages in the ‘requirements.txt’ file with pip :
After completing the project’s installation and setup, we are now going to set up the database for our application.
To keep this simple, we will use SQLite for this project.
SQLite is a small, simple database that stores all its data in one file. It doesn’t require a server to run, making it easy to use in apps and small projects.
Use the following code to install SQLite :
After installing sqlite3 to your system, we will now create a database named “bookstore” consisting of two tables :
Users table will store registered users. We will also keep a check, allowing only the registered users to access the Books table.
Books table will store the details and information about books, such as the book’s name, author of the book, publication of the book, and submitted by the registered users.
To create the database, run the following command :
For checking if you have successfully created the database or not run the below command:
If the database is created successfully, we will go ahead and create a new file named “app.py” in the myflaskproject directory or run this command in your terminal:
NOTE- while executing commands in the terminal, ensure you do it inside the virtual environment named “venv” we created earlier.
Now, paste the following code inside the python file named app.py:
from flask import Flask, jsonify, make_response, request from werkzeug.security import generate_password_hash,check_password_hash from flask_sqlalchemy import SQLAlchemy from functools import wraps import uuid import jwt import datetime
Let’s see what is the purpose of importing the packages mentioned above :
⦿ Packages from Flask framework
⦿ Package from SQLAlchemy
⦿ Package from werkzeug.security
⦿ datetime: The package datetime will help us manipulate date and time as date objects. We need this module because python does not have any data type to support dates.
⦿ uuid– Universal Unique Identifiers create random ID numbers for users. The uuid is a very useful package, especially for database engines that do not support incremental primary key features. Also, using multi-character alpha-numeric values as IDs is better than using linearly incremental numeric IDs.
Now it’s time to configure settings for the Bookstore API inside the app.py file using the below code.
app = Flask(__name__) app.config['SECRET_KEY']='004f2af45d3a4e161a7dd2d17fdae47f' app.config['SQLALCHEMY_DATABASE_URI']='sqlite:///PATH_TO_YOUR_SQLITE3_DB_FILE' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True db = SQLAlchemy(app)
Here, the value assigned to the config variable ‘SECRET KEY’ can be auto-generated using a python library named ‘secrets.’ As shown below, we can simply run the following code in your terminal to generate this value.
Now, we will create two models for the Books and Users table.
Copy the code below to your app.py file or create your own models.
class Users(db.Model): id = db.Column(db.Integer, primary_key=True) public_id = db.Column(db.Integer) name = db.Column(db.String(50)) password = db.Column(db.String(50)) admin = db.Column(db.Boolean)
class Books(db.Model): id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) name = db.Column(db.String(50), unique=True, nullable=False) Author = db.Column(db.String(50), unique=True, nullable=False) Publisher = db.Column(db.String(50), nullable=False) book_prize = db.Column(db.Integer)
Moving ahead with Flask-JWT Authentication Tutorial.Now we are going to create the tables from the models we have created, to do so add the below code to your app.py file for creating tables for both models:
Now, go to the app.py file and create the other functions required.
We create a ‘token_required(f)’ function that will generate tokens to allow only registered users to access and manipulate a set of API operations against the Books table.
Simply paste the following code after the database model for both tables.
def token_required(f): @wraps(f) def decorator(*args, **kwargs): token = None if 'x-access-tokens' in request.headers: token = request.headers['x-access-tokens'] if not token: return jsonify({'message': 'a valid token is missing'}) try: data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=["HS256"]) current_user = Users.query.filter_by(public_id=data['public_id']).first() except: return jsonify({'message': 'token is invalid'}) return f(current_user, *args, **kwargs) return decorator
This code is a special function. This function will create a custom decorator with the code required to create and validate tokens. Python provides an amazing feature called function decorators, which allows very neat features for web development.
In Flask, each view is considered a function, and decorators are used to inject additional functionality into one or more functions. In this case, this custom decorator will handle creating and validating tokens.
In this step, we will generate a route for allowing users to register for the Books API using their name and password. With this route, we will create a view to encrypt the user’s password, store the new user’s details in the database, and return a success message.
Again, inside the app.py file, paste the following code after the token_required(f) function:
@app.route('/register', methods=['POST']) def signup_user(): data = request.get_json() hashed_password = generate_password_hash(data['password'], method='sha256') new_user = Users(public_id=str(uuid.uuid4()), name=data['name'], password=hashed_password, admin=False) db.session.add(new_user) db.session.commit() return jsonify({'message': 'registered successfully'})
Here,
Now, we will generate another route allowing all registered users to log in.
We will create a view to handle the user login feature with the login route. When a user logs in, the entered password matches the user’s stored password. A random token is generated to access the Bookstore API if the password matches successfully. For instance, we will keep the expiration time for this random token to 45 minutes.
You can add the below-mentioned code beneath the registered route we created in the previous step in your file:
@app.route('/login', methods=['POST']) def login_user(): auth = request.authorization if not auth or not auth.username or not auth.password: return make_response('could not verify', 401, {'Authentication': 'login required"'}) user = Users.query.filter_by(name=auth.username).first() if check_password_hash(user.password, auth.password): token = jwt.encode({'public_id' : user.public_id, 'exp' : datetime.datetime.utcnow() + datetime.timedelta(minutes=45)}, app.config['SECRET_KEY'], "HS256") return jsonify({'token' : token}) return make_response('could not verify', 401, {'Authentication': '"login required"'})
Here,
After authorization routes, let’s create another route in the app.py file to get all the registered users. This route verifies the registered users in the Users table and provides the output in JSON format. Use the below code after the login route.
@app.route('/users', methods=['GET']) def get_all_users(): users = Users.query.all() result = [] for user in users: user_data = {} user_data['public_id'] = user.public_id user_data['name'] = user.name user_data['password'] = user.password user_data['admin'] = user.admin result.append(user_data) return jsonify({'users': result})
After creating all the routes for the users, let’s create routes for the Books table. These routes will allow users to retrieve and delete all the books in the database. We will also implement a mandatory check to verify that users with valid tokens can only perform API requests.
Define a route for all the registered users to create a new book. The following code creates a route to meet this requirement:
@app.route('/book', methods=['POST']) @token_required def create_book(current_user): data = request.get_json() new_books = Books(name=data['name'], Author=data['Author'], Publisher=data['Publisher'], book_prize=data['book_prize'], user_id=current_user.id) db.session.add(new_books) db.session.commit() return jsonify({'message' : 'new books created'})
Here,
Now, create a route to allow a logged-in user with a valid token to get all the books in the Books table as shown below:
@app.route('/books', methods=['GET']) @token_required def get_books(current_user): books = Books.query.filter_by(user_id=current_user.id).all() output = [] for book in books: book_data = {} book_data['id'] = book.id book_data['name'] = book.name book_data['Author'] = book.Author book_data['Publisher'] = book.Publisher book_data['book_prize'] = book.book_prize output.append(book_data) return jsonify({'list_of_books' : output})
Here,
Finally, we will create the last route to delete a specific book. We will make a view responsible for handling requests to delete an existing record in the Books table. If it exists, it will verify and delete the given record from the DB.
The code mentioned below can be implemented after the route allows the user to retrieve a list of books.
@app.route('/books/ ', methods=['DELETE']) @token_required def delete_book(current_user, book_id): book = Books.query.filter_by(id=book_id, user_id=current_user.id).first() if not book: return jsonify({'message': 'book does not exist'}) db.session.delete(book) db.session.commit() return jsonify({'message': 'Book deleted'}) if __name__ == '__main__': app.run(debug=True)
Now run the app.py file by using the following command inside the virtual environment in the appropriate directory.
If the above command does not work, here’s an alternative command.
The entire source code is here – Python Flask JWT Authentication Example.
In conclusion, this guide has walked you through the steps to implement Flask JWT Authentication, helping you easily secure your application. We hope this tutorial has fulfilled your expectations and provided valuable insights. If you have any questions or need expert assistance, we’re here to help. Get in touch today and let us help you create a secure, scalable, and feature-rich application. Hire Dedicated Flask Developer to take your project to the next level and ensure top-notch results. Don’t hesitate to reach out with your queries, suggestions, or feedback—we’d love to hear from you!
Flask is a minimal yet powerful framework with several advantages, including an inbuilt development server, simple URL routing, and high compatibility with modern technologies. Its smaller codebase ensures better performance and maintainability, making it an efficient choice for web development.
To install Flask on Linux, install Python and pip with sudo apt update && sudo apt install python3 python3-pip. Create a virtual environment using python3 -m venv flask_env, activate it with source flask_env/bin/activate, and install Flask using pip install Flask. Verify with python3 -m flask –version.
Flask is a microframework because it is lightweight and minimal, offering only the essentials for web development. It allows developers to add features as needed, making it flexible and ideal for small and complex projects.
Your Success Is Guaranteed !
We accelerate the release of digital product and guaranteed their success
We Use Slack, Jira & GitHub for Accurate Deployment and Effective Communication.