Securing FastAPI with JWT Authentication (JSON Web Tokens)

Posted by


FastAPI is a modern web framework for building APIs with Python. It is fast, easy to use, and provides native support for authentication using JSON Web Tokens (JWT). In this tutorial, we will walk through the process of setting up authentication with JWT in a FastAPI application.

What is JWT?
JSON Web Tokens (JWT) are a standard method for securely transmitting information between parties as a JSON object. They are compact, self-contained, and can be easily transmitted as a URL parameter, a cookie, or within an HTTP header. JWTs are commonly used for authentication and information exchange in web applications.

Setting up a FastAPI Application
First, let’s create a new FastAPI application and install the necessary dependencies:

pip install fastapi
pip install uvicorn
pip install pyjwt

Next, create a new Python file for your FastAPI application, for example main.py, and import the required modules:

from fastapi import FastAPI
from fastapi.security import OAuth2PasswordBearer
from pydantic import BaseModel
from typing import Optional
from datetime import datetime, timedelta
import jwt

Creating a User Model
Next, let’s define a user model using Pydantic to store user information. This model will be used for authentication and authorization:

class User(BaseModel):
    id: int
    username: str
    email: str
    password: str

In a real-world application, you would typically use a database to store user data and retrieve it when needed.

Generating JWT
We will now create a function to generate a JWT token when a user successfully logs in. The token will contain the user’s id and an expiration time:

def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(hours=24)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, "SECRET_KEY", algorithm="HS256")
    return encoded_jwt

In a real-world scenario, you should store the SECRET_KEY securely and not hardcode it in your application.

Authenticating Users
Now, let’s create a route for user authentication where users can log in using their credentials:

app = FastAPI()

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
    # Authenticate user
    user = authenticate_user(form_data.username, form_data.password)

    if not user:
        raise HTTPException(status_code=400, detail="Incorrect username or password")

    access_token = create_access_token(data={"sub": user.id})
    return {"access_token": access_token, "token_type": "bearer"}

In this route, we authenticate the user by checking their credentials against the database. If the credentials are correct, we generate a JWT token using the create_access_token function and return it to the user.

Protecting Routes
To protect routes with authentication, you can use the OAuth2PasswordBearer security dependency provided by FastAPI. Here’s an example of how you can use it to secure a route:

from fastapi import Depends
from fastapi.security import OAuth2PasswordBearer

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

@app.get("/users/me")
async def read_users_me(token: str = Depends(oauth2_scheme)):
    # Verify token
    try:
        payload = jwt.decode(token, "SECRET_KEY", algorithms=["HS256"])
        user_id = payload.get("sub")
        user = get_user_by_id(user_id)
        if user is None:
            raise HTTPException(status_code=401, detail="Invalid token")
        return user
    except jwt.ExpiredSignatureError:
        raise HTTPException(status_code=401, detail="Token has expired")
    except jwt.InvalidTokenError:
        raise HTTPException(status_code=401, detail="Invalid token")

In this route, we use the OAuth2PasswordBearer dependency to extract the JWT token from the request header. We then decode the token using the jwt.decode function and verify its contents. If the token is valid, we return the user’s information.

Conclusion
In this tutorial, we have walked through the process of setting up authentication with JWT in a FastAPI application. By following these steps, you can secure your API endpoints and authenticate users effectively. FastAPI provides built-in support for authentication and authorization, making it easy to implement secure web applications.

0 0 votes
Article Rating
40 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
@carlosvelazquez7979
2 months ago

Wooo, what a great great Video !!!!!, Excellent I do appreciate it !!!, I've been developing softWare for 40 years ( since I was 14 ), few videos like this one !!, and I've watched lots !!!

@Antinormanisto
2 months ago

why decode_token['expiry'] >= time.time()??

@MaxoSall
2 months ago

I have yet to see any tutorials about actual atheoriaztion and permissions in fastapi

@user-yr8tm1cd1k
2 months ago

Это отличное видео! Всё чётко и подробно!

@kz_cbble9670
2 months ago

Even if i post the wrong acces token in authorize , it still allows me to post.. what's wrong?

@kz_cbble9670
2 months ago

37:46

@user-ln6hz2nb7o
2 months ago

i wish it was more deep

@pramudyadika_
2 months ago

thanks! ur explanation is crystal clear!

@razapanjwani6502
2 months ago

How does the server tell client side that a user is logged in?

@user-ms9cl1rf9w
2 months ago

Hey, Bek have just subscribed your channel for developing & learning software skiils,
I like your teaching skills that there is silent background music with your slowly teaching techniques & explanation + hands-on.
your videos on Django is on of the great Tutorial for me …!
Thanks man…

@ardianwebikirda6045
2 months ago

I immediately became your subscriber, when I saw your codes on GitHub didn't use OAuth, this is what I Need Thanks a lot buddy. Awesome

@devpriyashivani1855
2 months ago

Tried multiple times but finally got the error: { "detail": "Invalid token or expired token." }

@LearnWithAshiii
2 months ago

You have Done a Great Job
respect from Pakistan ❤

@michaelehrenreich
2 months ago

Excellent, I enjoyed this video very much!

@mehul4mak
2 months ago

@21.24 how come you are getting I'd 4 and 5 if you are posting Id 0?

@piuskariuki5295
2 months ago

This is friggin AWESOME

@mycala6
2 months ago

Can anyone help me out.
I have one doubt suppose you have 2 users (student and admin)how to use the generated token during login, only for the student specified tag user I logged in and it's methods and that token should not be able to be used by the admin methods,
To perform operations on admin again we need to create token for that.

@user-wo1qc2hp6z
2 months ago

hi bek,if i want to update user information using PUT method of a specific user,how can i use the token that was generated in login and user the same token in PUT method to represent that same user and update only the details of that specific user

@user-wo1qc2hp6z
2 months ago

Thank you man,it was a nice one,really learnt and understood what i was working on

@sziller_eu
2 months ago

In the last step, does it give an error if I slightly change the token pasted? Also how can I read data from the token once inside a function?