0% found this document useful (0 votes)
3 views7 pages

Understanding Dependencies in FastAPI

The document explains how to use dependencies in FastAPI to simplify route logic by offloading tasks like user authentication and role checking to separate functions or classes. It provides examples of both function-based and class-based dependencies, demonstrating how to protect endpoints and validate user access tokens. Additionally, it highlights the ability to create nested dependencies for more complex authorization scenarios.

Uploaded by

Nash
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views7 pages

Understanding Dependencies in FastAPI

The document explains how to use dependencies in FastAPI to simplify route logic by offloading tasks like user authentication and role checking to separate functions or classes. It provides examples of both function-based and class-based dependencies, demonstrating how to protect endpoints and validate user access tokens. Additionally, it highlights the ability to create nested dependencies for more complex authorization scenarios.

Uploaded by

Nash
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

Understanding Dependencies in

FastAPI
Jun 7, 2025 • 5 min read
Tags: Python, FastAPI, Dependency

What are dependencies?


We can think of dependencies as helpers for our routes without cluttering up the main
logic. Need to check if a user is logged in? Grab a database connection? Instead of
cramming all of that into your route function, you offload it to a dependency—a
separate function (or class) that handles one specific job.

You just say, “Hey, I need X” with Depends(X), and FastAPI will make sure X is ready
and available when your route runs.

Sample dependency in action


Now lets see how dependency can make our life easier.

Let’s say that you have a database of users, and you want to protect your endpoints
from unauthorized users. Below is the sample code.

To make things simple, we will use a Python dict to store the users.

from fastapi import FastAPI

app = FastAPI()

USERS = [
{
"id": 1,
"name": "John Doe",
"role": "admin",
"access_token": "token111"
},
{
"id": 2,
"name": "Jane Doe",
"role": "user",
"access_token": "token222"
}
]

nashruddinamin.com
Web Development and AI - Python, React, Rust. ​ ​ ​ ​ ​ 1
@app.get('/protected1')
async def protected1():
return {"message": "You are accessing our protected 1"}

@app.get('/protected2')
async def protected2():
return {"message": "You are accessing our protected 2"}

We want the users to pass their access token when making the HTTP requests to our
endpoints. This access token will be checked against the database, and only users
with valid access token are allowed to access the endpoint.

To avoid repeating the same token validation logic in every endpoint, we can use
FastAPI’s dependency injection system.

Create a simple dependency to handle the access token check:

# New imports: Header, HTTPException, Depends


from fastapi import FastAPI, Header, HTTPException, Depends

def get_current_user(access_token: str = Header(...)):


for user in USERS:
if user["access_token"] == access_token:
return user
raise HTTPException(status_code=401, detail="Invalid or missing token")
...

Let’s break down the code above:

1.​ We define a function get_current_user.


2.​ It expects the Access-Token header in the HTTP request.
3.​ It loops through the USERS list to find a match.
4.​ Return the user with the matches access token.
5.​ If no match is found, raise a HTTP 401 error.

Now we can apply this dependency to our endpoints like this:

from typing import Annotated

nashruddinamin.com
Web Development and AI - Python, React, Rust. ​ ​ ​ ​ ​ 2
...

@app.get('/protected1')
async def protected1(user: Annotated[dict, Depends(get_current_user)]):
return {"message": f"Hello, {user['name']}! You are on protected 1"}

@app.get('/protected2')
async def protected2(user: Annotated[dict, Depends(get_current_user)]):
return {"message": f"Hello, {user['name']}! You are accessing our
protected 2"}

Boom! Now both endpoints are protected. FastAPI will run the get_current_user
function before hitting our endpoint, and if it passes, the user object is injected into the
endpoint.

If user John Doe want to access the protected endpoints, he needs to pass his access
token when making the requests:

$ curl http://localhost:8000/protected1 -H "Access-Token: token111"


{"message":"Hello, John Doe! You are accessing our protected 1"}

Can I write dependency that depends on other


dependency?
Yes, you can!

In FastAPI, a nested dependency happens when a dependency function itself


depends on another dependency. This allows you to build modular and reusable logic
without cluttering your endpoints.

Lets say we have another endpoint, /admin-only, that requires not only user with
valid access token, but they should also have the “admin” role.

We can write the code like this:

...

def has_role(required_role: str):


def role_checker(user: Annotated[dict, Depends(get_current_user)]):
if user['role'] == required_role:
return user
raise HTTPException(status_code=403, detail="Forbidden")
return role_checker

nashruddinamin.com
Web Development and AI - Python, React, Rust. ​ ​ ​ ​ ​ 3
@app.get('/admin-only')
async def admin_only(user: Annotated[dict, Depends(has_role('admin'))]):
return {"message": f"Hello, {user['name']! You are accessing our
admin-only endpoint"}

Here, role_checker depends on get_current_user. When a request hits the


/admin-only endpoint, FastAPI will first resolve get_current_user to get the
current user from the Access-Token header. If succeed, that user object is then
passed to role_checker, which checks if the user’s role matches the required role.

This chain continues until all dependencies are resolved, and finally, the endpoint
function runs with the validated user object.

The cool part is — you can stack or nest as many dependencies as you like, keeping
your endpoint functions clean and focused only on the business logic.

Class-based dependencies
You are not limited to use function-based dependencies only. You can also use
class-based dependencies for your route functions.

For example, we can rewrite the get_current_user and has_role dependencies


above into class-based dependencies like the following:

class CurrentUser(object):
def __call__(self, access_token: str = Header(...)):
for user in USERS:
if user["access_token"] == access_token:
return user
raise HTTPException(
status_code=401,
detail="Invalid or missing token"
)

class RoleChecker(object):
def __init__(self, required_role: str):
self.required_role = required_role

def __call__(self, user: Annotated[dict, Depends(CurrentUser())]):


if user['role'] == self.required_role:
return user
raise HTTPException(status_code=403, detail="Forbidden")

Apply the dependencies to the routes:

nashruddinamin.com
Web Development and AI - Python, React, Rust. ​ ​ ​ ​ ​ 4
@app.get('/protected1')
async def protected1(user: Annotated[dict, Depends(CurrentUser())]):
...

@app.get('/protected2')
async def protected2(user: Annotated[dict, Depends(CurrentUser())]):
...

@app.get('/admin-only')
async def admin_only(user: Annotated[dict, Depends(RoleChecker('admin'))]):
...

Just like before, the /protected1 and /protected2 endpoints only require a valid
token, while /admin-only checks both the token and that the user has the “admin”
role.

Also note that it is still a nested dependencies like before–RoleChecker depends on


CurrentUser to get the authenticated user before checking their role.

The complete code


Below is the complete code for your reference:

from typing import Annotated


from fastapi import FastAPI, Header, HTTPException, Depends

app = FastAPI()

USERS = [
{
"id": 1,
"name": "John Doe",
"role": "admin",
"access_token": "token111"
},
{
"id": 2,
"name": "Jane Doe",
"role": "user",
"access_token": "token222"
}
]

def get_current_user(access_token: str = Header(...)):

nashruddinamin.com
Web Development and AI - Python, React, Rust. ​ ​ ​ ​ ​ 5
for user in USERS:
if user["access_token"] == access_token:
return user
raise HTTPException(status_code=401, detail="Invalid or missing token")

def has_role(required_role: str):


def role_checker(user: Annotated[dict, Depends(get_current_user)]):
if user['role'] == required_role:
return user
raise HTTPException(status_code=403, detail="Forbidden")
return role_checker

class CurrentUser(object):
"""
Class-based version of the `get_current_user` dependency
"""
def __call__(self, access_token: str = Header(...)):
for user in USERS:
if user["access_token"] == access_token:
return user
raise HTTPException(status_code=401, detail="Invalid or missing
token")

class RoleChecker(object):
"""
Class-based version of the `has_role` dependency
"""
def __init__(self, required_role: str):
self.required_role = required_role

def __call__(self, user: Annotated[dict, Depends(CurrentUser())]):


if user['role'] == self.required_role:
return user
raise HTTPException(status_code=403, detail="Forbidden")

@app.get('/protected1')
async def protected1(user: Annotated[dict, Depends(get_current_user)]):
return {"message": f"Hello, {user['name']}! You are accessing our
protected 1"}

@app.get('/protected2')
async def protected2(user: Annotated[dict, Depends(get_current_user)]):
return {"message": f"Hello, {user['name']}! You are accessing our
protected 2"}

@app.get('/admin-only')

nashruddinamin.com
Web Development and AI - Python, React, Rust. ​ ​ ​ ​ ​ 6
async def admin_only(user: Annotated[dict, Depends(has_role('admin'))]):
return {"message": f"Hello, {user['name']}! You are accessing our admin
endpoint"}

nashruddinamin.com
Web Development and AI - Python, React, Rust. ​ ​ ​ ​ ​ 7

You might also like