Authentication APIs in FastAPI (Python Framework): Register, Get Token, Refresh Token, and User Details

Posted by


FastAPI is a modern Python web framework that simplifies the process of building APIs with high performance and great documentation. In this tutorial, we will focus on implementing authentication APIs using FastAPI. We will cover the following endpoints – Register, GET Token, Refresh Token, and User Details.

  1. Setting up the project:
    Firstly, make sure you have Python and FastAPI installed. You can install FastAPI using pip:
pip install fastapi
pip install uvicorn

Create a new Python file, let’s call it main.py. This will be our main FastAPI file.

  1. Define models:
    We will need to define the models for our user and tokens. Create a models.py file and add the following code:
from pydantic import BaseModel

class User(BaseModel):
    username: str
    password: str

class Token(BaseModel):
    access_token: str
    token_type: str

class UserInDB(User):
    hashed_password: str
  1. Implement the endpoints:
    In our main.py file, we will define our endpoints for authentication. Here is how you can implement them:
from fastapi import FastAPI, HTTPException, Depends
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jwt import PyJWTError, decode, encode
from passlib.context import CryptContext
from datetime import datetime, timedelta
from typing import Optional

from models import User, Token, UserInDB

app = FastAPI()
security = OAuth2PasswordBearer(tokenUrl="/token")

# Secret key
SECRET_KEY = "your_secret_key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

# User database
fake_users_db = {
    "johndoe": {
        "username": "johndoe",
        "full_name": "John Doe",
        "email": "johndoe@example.com",
        "hashed_password": "$2b$12$EY/a9eOzVta9jj5/93o7BOlMuQ9fowmH5jz/Fo65t8hjijNUCeEqS" #hashed password - password123
    }
}

# Password hashing
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

# Authenticate User
def authenticate_user(username: str, password: str):
    user = fake_users_db.get(username)
    if not user:
        return False
    if not pwd_context.verify(password, user["hashed_password"]):
        return False
    return user

# Get user
def get_current_user(token: str = Depends(security)):
    credentials_exception = HTTPException(
        status_code=401,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
    except PyJWTError:
        raise credentials_exception

    user = fake_users_db.get(username)
    if user is None:
        raise credentials_exception
    return user

# Create access token
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(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

# Register user
@app.post("/register", response_model=User)
async def register_user(user: User):
    if user.username in fake_users_db:
        raise HTTPException(status_code=400, detail="Username already registered")
    fake_users_db[user.username] = {
        "username": user.username,
        "full_name": user.username,
        "email": user.username + "@example.com",
        "hashed_password": pwd_context.hash(user.password)
    }
    return user

# Get Token
@app.post("/token", response_model=Token)
async def get_token(form_data: OAuth2PasswordRequestForm = Depends()):
    user = authenticate_user(form_data.username, form_data.password)
    if not user:
        raise HTTPException(status_code=400, detail="Incorrect username or password")
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(data={"sub": user["username"]}, expires_delta=access_token_expires)
    return {"access_token": access_token, "token_type": "bearer"}

# Refresh Token
@app.post("/refresh_token", response_model=Token)
async def refresh_token(user: User = Depends(get_current_user)):
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(data={"sub": user["username"]}, expires_delta=access_token_expires)
    return {"access_token": access_token, "token_type": "bearer"}

# User Details
@app.get("/user/me", response_model=User)
async def read_users_me(user: User = Depends(get_current_user)):
    return user
  1. Running the application:
    You can run your FastAPI application using Uvicorn:
uvicorn main:app --reload

Now, you can test your authentication APIs using tools like Postman or curl. Here are the endpoints you can hit:

  • /register – to register a new user
  • /token – to get an access token by providing username and password
  • /refresh_token – to refresh the access token
  • /user/me – to get user details

Make sure to handle the authentication tokens securely and implement proper authorization and validation logic in your APIs.

This tutorial covers the basic implementation of authentication APIs using FastAPI. You can further enhance your authentication logic by adding features like JWT blacklisting, role-based access control, and more. FastAPI makes it easy to build secure and performant APIs with Python. Happy coding!

0 0 votes
Article Rating

Leave a Reply

27 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
@laurentvelez9425
2 hours ago

Congrats. Impressive work

@1977spaul
2 hours ago

Very nice tutorial. Thanks a lot.

@meet_gondaliya
2 hours ago

Awesome video. I learnt so much about authentication in general. I was looking to setup fastapi just like Django and this video helped me do that. Thank you 🙂

@martinmiz
2 hours ago

Great tutorial. It was challenging, but I managed to work my way to the end. Thanks a lot!

@AnubhavRohatgiDelhi
2 hours ago

This still does not explain how can I use refresh tokens. When I use PasswordBearer, then no refreshtoken is exposed in the response, which I can copy and use to generate another access token. Also how can I update the cookie with the new token ?

@fam9185
2 hours ago

what is the difference between access and refresh tokens? in this code u can use a refresh token as aceess for autorisation. so where is the safety here? besides, refresh token has no expiration time

@Htyagi1998
2 hours ago

Rather than using any db to store the id and passwd can we use any secure vault like hashicprp to save the details ?

@Htyagi1998
2 hours ago

Great work ❤

@codepark.online
2 hours ago

thank you!

@mehul4mak
2 hours ago

Why your endpoints does not have lock icon for oauth2?

@dubey_ji
2 hours ago

awesome man !
thanks for this

@mdaslamknl
2 hours ago

Good

How can i setup database in mysql

Thanks

@girigaurav
2 hours ago

In 1:16:56 , UserResponse should inherit BaseResponse not BaseModel.

@avinashsudhanshu
2 hours ago

can you do same with mongo

@alexeymatveev9031
2 hours ago

this training is wider than just for JWT, but it's very good. It was difficult to go through MySQL setup though

@ibrahimethem5779
2 hours ago

Hello, can you prepare video content by adding Rabbitmq, Kafka, Redis technologies into this API?

@anuj7286
2 hours ago

Thank you for explaning this!

@nutandevjoshi
2 hours ago

Thanks for the tutorial

@sarkaran
2 hours ago

1. refresh token doesn't have expiration time,
2. use can access protected endpoints using both refresh token and access token.
refresh token should only be used to obtain new access token

it is not a good practice

@karapython
2 hours ago

what i like about your video is you do your job with blind eyes not even debug it's okay when you do yourself but when you are teaching it's different

27
0
Would love your thoughts, please comment.x
()
x