TheLearningDev's Blog

TheLearningDev's Blog

How to Implement JWT based Authentication in Python Flask?

Authentication ensures that the users have access to the system. There are different kinds of auth systems in general. Here is a compilation of different Authentication methods and ideas behind it

The following blog is a part of 4 weeks Python to Project Bootcamp where Python beginners step up their Python skills and build their own projects

JWT based authentication

  • Works for mobile-based, web-based, and microservices-based auth
  • Relatively easy to implement

Let's start the implementation.

Install Flask-Jwt Library

pip install Flask-JWT

Initiallize JWT object

JWT needs a private key to decode the JWT token. Here it's super-secret. In production systems, we usually have this key in a.env` file. If a secret key of an application is exposed, anyone can start using the APIs generating API tokens.

Note: For the implementation of this blog, use the Python Flask Project template from here

# File:: app.py

app.config['SECRET_KEY'] = 'super-secret'
app.config['JWT_EXPIRATION_DELTA'] = timedelta(seconds=3000)

Create a User Model in models.py

# File:: models.py

class User(db.Model):
    username = db.Column(db.String(80),  primary_key=True, nullable=False)
    password = db.Column(db.String(120))

Write an authenticate function.

Flask-JWT uses two functions for auth purposes.

1. Authenticate

Logs in the user for the first time and returns the user object. Internally, JWT uses this object to create a JWT token.

2. Identity

The identity function is used on all protected APIs. Internally, flask-jwt decodes the JWT token, gets the user_id, and passes it to the identity function.

# File:: api.py

from flask_jwt import jwt_required, JWT, current_identity

def identity(payload):
    user_id = payload['identity']
    return User.query.filter_by(id=user_id).first()

def authenticate(username, password):
    user = User.query.filter_by(username=username).first()
    if user and user.password == password:
        return user

jwt = JWT(app, authenticate, identity)

Write Signup and Authenticated views

# File:: api.py

@app.route("/signup", methods=["POST"])
def signup():
    params = request.json()
    try:
        user = User(**params)
        db.session.add(user)
        db.session.commit()
    except IntegrityError:
        return {"Status": "Error", "result": "User already exists"}, 400
    return {"Status": "Success", "result": "User created"}

To authenticate your APIs, you need to add the decorator jwt_required to the view function.

@app.route("/hello")
@jwt_required()
def hello_world():
    return {"Status": "Success", "result": f"Hello {current_identity.username}"}

Let's Test Authentication

User Sign Up

Let's use /signup API to create the user

import requests
params = {
    "username": "joe",
    "password": "pass"
}

response = requests.post("/signup", json=params)
print (response.json())

User Login

/auth is an API that comes as default in the flask-jwt package. To log in, a user makes an API call with a username and password.

import requests
params = {
    "username": "joe",
    "password": "pass"
}

response = requests.post("/auth", json=params)
print (response.json())

Authenticating Future Requests

The above snippet will return a JSON response with a JWT Token. Future requests can use JWT Token for authentication.

headers = {
    "Authorization" : "JWT <token>"
}
requests.get("/hello", headers=headers)
 
Share this