FastAPI is a fast and easy Python framework for building APIs. It’s as fast as Node.js and Go, with built-in support for authentication, type checking, and auto-generated docs.
Authentication verifies who a user is, while authorization controls what they can do. These are essential for protecting user data and preventing unauthorized access.
This guide will show you how to add secure authentication and authorization to your FastAPI app—from basic logins to OAuth2 with JWT.
Prerequisites
Before you begin, make sure you have Python 3.8 or higher and pip installed. This guide assumes you know basic Python, web development, and REST APIs. Some knowledge of JWT tokens and OAuth2 is helpful, but don’t worry—we’ll explain them as we go.
Getting started with FastAPI authentication
To follow along with this tutorial effectively, you'll create a new FastAPI project from scratch.
Start by setting up your development environment:
Now, install the required dependencies for your authentication system:
Here's what each package does in your authentication system:
fastapiprovides the web framework foundationuvicornserves as your ASGI server for running the applicationpython-josehandles JWT token creation and validationpasslibwithbcryptmanages secure password hashingpython-multipartenables form data parsing for login endpoints
Create a new main.py file in your project directory and add this foundational code:
Start the development server to make sure everything works correctly:
Navigate to http://localhost:8000 in your browser, and you should see the welcome message:
You can also visit http://localhost:8000/docs to explore FastAPI's automatic interactive API documentation powered by Swagger UI:
Once that’s working, you’re ready to move on to the next step.
Understanding FastAPI's security framework
FastAPI features a built-in security system that adheres to the OpenAPI standard. It makes it easy to add different types of authentication like API keys, HTTP Basic authentication, OAuth2 with JWT tokens, and even custom options.
It uses dependency injection to handle security. This means you can create reusable functions for authentication and apply them to specific endpoints or entire groups of routes. This helps keep your code clean and makes it easier to manage access across your app.
FastAPI also automatically updates your API documentation with the correct security information. This helps others understand how to connect to your API and what kind of authentication is needed.
Implementing basic authentication
To start, we’ll use HTTP Basic authentication. This method isn’t recommended for production due to its security limitations, but it helps learn how FastAPI’s security system works.
Create a new file named auth.py and add the following code:
Now update your main.py file to use this authentication:
The authenticate_user function shows several important concepts. You use secrets.compare_digest() for secure string comparison, which prevents timing attacks by ensuring the comparison takes a constant amount of time regardless of where the strings differ. The HTTPException with a 401 status code properly signals authentication failure to the client.
When you visit the /protected endpoint in your browser or API documentation, you'll get prompted to enter credentials. The browser will display a login dialog, and you'll need to enter "admin" as the username and "secret" as the password to access the protected resource:
After entering the correct credentials, you'll be redirected to the protected route and see a message like this:
Now that you’ve seen how basic authentication works, let’s move on to making it more secure.
Password hashing and user management
Production apps should never store passwords in plain text. Instead, you need to hash passwords using secure algorithms. Let's build a better user system with proper password hashing.
First, create a models.py file to define your user data structures:
Now, let's start building the authentication system. Replace your auth.py file with the imports and configuration:
This sets up the basic configuration. The CryptContext handles password hashing using bcrypt, and OAuth2PasswordBearer prepares us for JWT token authentication (which we'll add next).
Next, add the fake database and password functions:
The fake database contains a user with a pre-hashed password. The hashed password corresponds to the plain text "secret". The two functions handle password hashing and verification using bcrypt.
Finally, add the user lookup and authentication functions:
These functions handle user lookup and authentication. get_user finds a user in the database, and authenticate_user checks if the provided username and password are correct by verifying the hashed password.
Now your authentication system uses secure password hashing and is ready for the next step where you will implement JWT tokens.
JWT token-based authentication
JSON Web Tokens (JWT) provide a secure way to authenticate users without storing sessions on the server. Each token contains all the user information needed, making your API stateless and scalable.
Let's add JWT token creation to your auth.py file:
This function creates a JWT token with an expiration time. The token includes the user data and is signed with your secret key to prevent tampering. We use datetime.now(datetime.timezone.utc) for proper timezone-aware UTC timestamps.
Next, add the token validation functions:
These functions extract the user information from the JWT token and verify it's valid. The get_current_active_user function adds an extra check to make sure the user account isn't disabled.
Now update your main.py file to create a login endpoint and use JWT authentication:
The /token endpoint accepts username and password, then returns a JWT token. The /users/me endpoint shows how to get the current user's information using the token.
Now restart your server and visit http://localhost:8000/docs. You'll see the new authentication system in action:
Click the "Authorize" button, enter "johndoe" as username and "secret" as password, then try accessing the protected routes:
Fill in the login form with your credentials:
You'll see how JWT tokens work seamlessly with FastAPI's automatic documentation. Once authorized, you can access protected routes:
Your API now uses secure JWT tokens instead of basic authentication, making it ready for production use.
Working with a database
While our examples have used in-memory storage, production applications need persistent data storage. Let's integrate with a real database using SQLAlchemy and show you how to implement authentication with proper database operations.
First, install the required database dependencies:
For this tutorial, we'll use SQLite since it doesn't require additional setup. In production, you'd typically use PostgreSQL or MySQL.
Create a database.py file for your database configuration:
This sets up your database schema with proper relationships between users and roles. The get_db function provides a database session for your endpoints.
Next, create database operations in a crud.py file:
These functions handle all your database operations, from creating users to authentication.
Now, update your authentication system to work with the database. Update your auth.py file. First, remove the old fake database and functions that are no longer needed:
Then, update the imports and add the new database functions:
The key changes are using the database session and converting between database models and Pydantic models.
Finally, update your main.py file to use the database:
Now you need to create the initial roles in your database. Create a simple script to set up your database:
You'll also need to add the missing function to crud.py:
Run the setup script to initialize your database:
Now restart your server and test the new database-backed authentication system:
Visit http://localhost:8000/docs to see the new /register endpoint in your API documentation:
Test the registration by clicking on the /register endpoint and trying to register a new user:
Fill in the registration form with sample data like:
After successful registration, you'll see the created user response:
Now test logging in with your newly registered user. Go to the /token endpoint and use the credentials you just created:
Your authentication system now uses a real database for persistent storage, making it ready for production deployment!
Next steps
You've built a complete authentication system with FastAPI that includes user registration, JWT tokens, and database integration. Your API now has the foundation needed for real-world applications.
To take your authentication further, explore FastAPI's documentation on advanced security topics including OAuth2 scopes, dependency injection patterns, and middleware integration. The database documentation covers more advanced SQLAlchemy patterns and async database operations.
For production deployments, review the deployment guide which covers environment configuration, HTTPS setup, and containerization best practices.