Skip to content

Example

This is a JWT Login/Logout Example with Refresh Tokens.

In this example we're using a Fake DB!

from typing import Dict, Union

from aioredis import Redis
from fastapi import FastAPI, Depends, HTTPException

from fastapi_framework import (
    redis_dependency,
    get_data,
    pwd_context,
    invalidate_refresh_token,
    check_refresh_token,
    get_token,
    generate_tokens,
)

app = FastAPI()

fake_user_db: Dict[int, Dict[str, str]] = {
    0: {
        "id": "0",
        "username": "test",
        "password": "$2b$12$vywwXgt8aHzb8PGhTvkZB.y20PzMfBxPr2i9ljr8QFUY6pe7DGWtG",  # Password is '123'
    },
    1: {
        "id": "1",
        "username": "admin",
        "password": "$2b$12$Uelb/O331cMgXgzdWo6mTO6nM1KS4fULNPzv.lBbEl4QCFQRjNzAi",  # Password is 'admin'
    },
}


@app.on_event("startup")
async def on_startup():
    await redis_dependency.init()


@app.get("/token")
async def token_route(username: str, password: str, redis: Redis = Depends(redis_dependency)):
    user: Union[Dict[str, str], None] = None
    for user_db in fake_user_db.values():
        if user_db["username"] == username:
            user = user_db.copy()
            break
    if user is None or not pwd_context.verify(password, user["password"]):
        raise HTTPException(401, detail="Username or Password is wrong")
    return await generate_tokens({"user": {"id": user["id"], "username": user["username"]}}, int(user["id"]), redis)


@app.get("/refresh")
async def refresh_route(refresh_token: str, redis: Redis = Depends(redis_dependency)):
    data: Dict = {}
    if not await check_refresh_token(refresh_token, redis):
        raise HTTPException(401, "Refresh Token Invalid")
    try:
        data = await get_data(refresh_token)
    except HTTPException as e:
        if e.detail == "Token is expired":
            await invalidate_refresh_token(refresh_token, redis)
            raise e
    user_id = int(data["user_id"])
    user = fake_user_db[user_id]
    await invalidate_refresh_token(refresh_token, redis)
    return await generate_tokens({"user": {"id": user["id"], "username": user["username"]}}, int(user["id"]), redis)


@app.get("/logout")
async def logout_route(refresh_token: str, redis: Redis = Depends(redis_dependency), _=Depends(get_token)):
    await invalidate_refresh_token(refresh_token, redis)


@app.get("/secret")
async def secured_route(data: Dict = Depends(get_data)):
    return f'Hello {data["user"]["username"]}!'