Rest Api in Flask with JSON Web Token in MySQL or MongoDB
Content Index
- What is a Json Web Token (JWT) and how does it work
- How to use a JWT token in a REST API
- Advantages over traditional sessions
- Requirements
- Installation of dependencies
- Creating the necessary methods to work with Flask JWT
- Implementing JWT authentication in Flask
- The identity and login or authentication functions in Flask JWT
- Authenticate function
- Identity function
- Global configurations:
- Configure protection in MySQL or MongoDB
- Protect the Rest API in Flask
- Necessary dependencies or installations
- Testing the API with Postman
- Solution to common errors with FlaskJWT and MongoDB
- Good security and maintenance practices
- Where to store JWTs
- Conclusion
- ❓ Frequently Asked Questions (FAQ)
Protecting a REST API with Json Web Tokens (JWT) in Flask is one of the most practical and secure ways to handle authentication without relying on sessions. In this guide, I show you how to implement JWT in Flask from scratch, also integrating FlaskUser and MongoDB, just as I have done in my own projects.
Json Web Token (JWT) is just a string that we send from the browser or client to our server in the request header; and this for the purpose of validating and verifying the client; of course, the server is responsible for generating the JWT with some condition on an existing user, which is generally to check a user and password pair.
What is a Json Web Token (JWT) and how does it work
A JWT is an encoded string used to verify a client's identity to the server. Instead of maintaining sessions, the client sends the token in the header of each HTTP request.
Structure of a JWT: Header, Payload, and Signature
The token is composed of three parts separated by dots:
header.payload.signature- Header: indicates the token type and encryption algorithm (e.g., HS256).
- Payload: contains the user data or claims.
- Signature: guarantees that the token has not been tampered with.
How to use a JWT token in a REST API
The flow is simple:
- The client logs in and sends username + password.
- The server validates the credentials and generates the token.
- The client includes that token in the header of each request:
Authorization: Bearer <token>
- Flask verifies the token's validity before allowing access to resources.
Advantages over traditional sessions
Scalable and no need to store sessions.
Compatible with microservices and SPA frontends.
Easy to revoke or expire.
Requirements
We are going to develop in several technologies as you can see, but to make a brief summary, you will need:
- Python in some version of 3.x
- A virtual environment on your computer
- MongoDB, you can perfectly use the terminal or some client
- Postman
- Your "Hello World" in Flask, or have some structure created
- To know how to create a Restful API in Flask
In this post, we are going to learn how to protect a Rest API created with the FlaskRestFul package with Json Web Token, the famous JWT, using the FlaskJWT package, employing Flask, of course; in addition to this, we are going to use the famous package called FlaskUser to manage the user's access credentials; that is, username and password.
Installation of dependencies
$ pip install flask flask-restful flask-jwt flask-user mongoengineCreating the necessary methods to work with Flask JWT
In this section, we will see what we need to configure to use Flask JWT in our Flask project; of course, these are general or example configurations and developments that you can use in any schema; in our case, we are going to use the FlaskUser package to handle everything related to login; in this case, we are interested in the function to manage credentials, specifically the use of the password.
Implementing JWT authentication in Flask
Within your Flask project, configure the database and user manager:
from flask_user import UserManager
from flask_mongoengine import MongoEngine
app = Flask(__name__)
app.config['MONGODB_SETTINGS'] = {'db': 'demo_jwt'}
db = MongoEngine(app)
user_manager = UserManager(app, db, User)I use MongoDB, but you can easily adapt to SQLAlchemy if you work with MySQL
We create the model for the user:
import mongoengine as models
from flask_user import UserMixin
import mongoengine as models
from flask_user import UserMixin
class User(models.Document, UserMixin):
active = models.BooleanField(default=True)
# User authentication information
username = models.StringField(default='')
password = models.StringField()
# User information
first_name = models.StringField(default='')
last_name = models.StringField(default='')
def __str__(self):
return self.username
class UserBase(object):
def __init__(self, id, username, password):
self.id = str(id)
self.username = username
self.password = password
def __str__(self):
return f"User id: {self.id}"You only need to create the UserBase class if you are going to use MongoDB to do the JSON parsing that is used internally by FlaskJWT; we simply use this class as an intermediary to return the authenticated user.
The identity and login or authentication functions in Flask JWT
To be able to use the FlaskJWT package, we have to create a couple of functions in its minimum configuration, the first to get the authenticated user given the identifier, called identity, and another function to handle the login, that is, compare the username and password; so:
from .models import User, UserBase
from proyect_app import user_manager
def autheticate(username, password):
user = User.objects(username=username).first()
if user_manager.verify_password(password,user):
userBase = UserBase(user.id, user.username, user.password)
return userBase
def identity(payload):
user_id = payload['identity']
user = User.objects(id=user_id).first()
return userAuthenticate function
For this function, which by default receives two parameters, the username and the password, we first search for the user and then verify the password, which is easy when using FlaskUser, and we can check the password using the function that FlaskUser provides us called verify_password; in the end, if everything is OK, we return the authenticated user.
Identity function
This function receives the payload, and we are interested in consuming the user ID, which we have as payload['identity'], and returning the user; it's that simple.
Global configurations:
At the level of our project, we have to create the configurations for JWT; it's the usual, and once the two previous functions are created, we import them and pass them as parameters to the corresponding class for Flask JWT:
# jwt
from proyect_app.user.jwt import autheticate, identity
jwt = JWT(app, autheticate, identity)The imports:
from flask_user import UserManager from flask_jwt import JWTAnd we configure our UserManager of our FlaskUser:
user_manager = UserManager(app, db, User)Configure protection in MySQL or MongoDB
Now, depending on the database engine we are using, for example MongoDB with the connector we are using in our MongoDB with Flask and Django course:
db = MongoEngine(app)or with SQLAlchemy that we can use, for example, MySQL:
db=SQLAlchemy(app)Protect the Rest API in Flask
Finally, we protect the RestApi in FlaskRestFul; for example, we have a resource type class and we indicate the corresponding decorator:
class BookApi(Resource):
decorators = [jwt_required()]You can find the complete project of the Flask with MongoDB course at:
For the user model, remember that we are also using FlaskUser, the usual, at least the username and password:
Necessary dependencies or installations
- https://pythonhosted.org/Flask-JWT/
- https://flask-user.readthedocs.io/en/latest/
- https://flask-restful.readthedocs.io/en/latest/
- http://docs.mongoengine.org/projects/flask-mongoengine/en/latest/
Testing the API with Postman
Once JWT is configured, we can test it.
Obtaining the authentication token
Send a POST request to /auth with:
{ "username": "usuario", "password": "clave" }Using the token in protected requests
Copy the generated token and place it in the headers:
Authorization: Bearer <token>Possible responses
- Code Description
- 200 Valid request, access allowed
- 401 Invalid or missing token
- 403 Expired token or unauthorized user
Postman was the most practical tool to verify the complete flow, especially when simulating authentication errors.
Solution to common errors with FlaskJWT and MongoDB
Some setbacks arise during implementation.
Error "ObjectId is not JSON serializable"
This problem appears when using MongoDB:
FlaskJWT tries to convert the user ID directly to JSON, which causes a failure.
Solution: return an instance of UserBase instead of the original MongoDB model.
This ensures that the ID is handled as a string.
Circular references when importing functions
Avoid importing authenticate and identity at the top of your __init__.py.
Do it after initializing app and db to prevent import errors.
Recommended modular structure
Divide your application into folders:
project_app/
├── user/
│ ├── models.py
│ ├── jwt.py
├── api/
│ ├── resources/
├── app.py
In my case, organizing the code this way greatly simplified testing and maintenance.
Good security and maintenance practices
Token expiration and renewal
Configure expiration:
app.config['JWT_EXPIRATION_DELTA'] = timedelta(seconds=3600)For renewals, implement a refresh endpoint if you use Flask-JWT-Extended.
Where to store JWTs
Avoid saving them in the browser's localStorage.
Use secure cookies (HttpOnly) or in-memory storage.
Flask-JWT vs Flask-JWT-Extended
Aspect Flask-JWT Flask-JWT-Extended
Simplicity ✅ Easy to configure ⚙️ More advanced options
Token renewal ❌ No ✅ Yes
Active support Limited Extensive
Recommended for Simple APIs Production projects
Conclusion
Implementing JWT in Flask allows for more modern and scalable authentication.
Combining FlaskUser with FlaskJWT allowed me to leverage the best of both worlds: robust password verification and token flexibility.
If you plan to work with MongoDB, remember to use a custom base class to avoid serialization errors and maintain the modular architecture from the start.
❓ Frequently Asked Questions (FAQ)
- What is the best library for JWT in Flask?
- Flask-JWT-Extended is the most complete currently, although Flask-JWT is still useful for small projects.
- Can I use JWT without a database in Flask?
- Yes, as long as the payload contains enough information to validate the user.
- How to revoke a token in Flask?
- Store the tokens in a revocation list (blacklist) and check each request.
- What is the difference between authentication and authorization?
- Authentication verifies who you are; authorization determines what you can do within the system.
I agree to receive announcements of interest about this Blog.
In this post we are going to know how we can work with Json Web Tokens in FlaskRestFul using MongoDB or MySQL with the FlaskUser package.