π₯Unit 18: JWT Authentication with FastAPI
Note:
This unit has been completely rewritten to use the pwdlib library, as the previously used passlib is now outdated and deprecated.
Heads-up: Be aware that AI code generators (like Google Gemini 2.5 and OpenAI's ChatGPT 5) may still suggest using the old passlib library. Please ensure you are using pwdlib as demonstrated in this tutorial.
Introduction
JWT (JSON Web Token) is a compact, secure means for transmitting information as a JSON object. It's commonly used for authentication and authorization purposes.
What is JWT?
A JSON Web Token (JWT), pronounced "jot," is an open standard (RFC 7519) for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs are compact, URL-safe, and commonly used for authentication and authorization in web applications and APIs, especially in microservices architectures.
Think of it like an event wristband. ποΈ
Self-contained: It contains all the information needed about you (e.g., your access level: VIP, General Admission).
Verifiable: Security can look at the wristband's color and design to verify it's authentic without needing to check a central database every time.
Tamper-proof: If you try to alter it, the change will be obvious, and you'll be denied entry.
JWT Structure
A JWT consists of three parts separated by dots (.), for example:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE3MjkzODQwMDB9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Header: Identifies which algorithm was used to generate the signature.
Content:
{"alg": "HS256", "typ": "JWT"}Format: Base64Url encoded.
Payload: Contains the "claims," which are statements about an entity (typically, the user) and additional data.
Content:
{"sub": "1234567890", "name": "John Doe", "iat": 1516239022, "exp": 1729384000}Standard Claims:
sub(subject/user ID),exp(expiration time),iat(issued at).Format: Base64Url encoded.
Signature: Used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn't changed along the way.
Creation: It's created by signing the encoded header, the encoded payload, and a secret key using the algorithm specified in the header.
Formula:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret_key)
Advantages of JWT
Stateless authentication
Secure information exchange
Easy integration with frontend frameworks
How JWT Authentication Works in FastAPI

Here's the typical JWT Bearer flow:
Login: A user sends their credentials (e.g., username and password) to a login endpoint (e.g.,
/token).Verification: The server validates the credentials against a database.
Token Creation: If the credentials are valid, the server creates a JWT, signing it with a secret key known only to the server. The payload contains user identifiers (like a user ID or username) and an expiration time.
Token Issuance: The server sends the JWT back to the client.
Token Storage: The client stores this token (e.g., in
localStorageor a secure cookie).Authenticated Requests: For every subsequent request to a protected endpoint, the client sends the JWT in the
Authorizationheader, using theBearerschema:Authorization: Bearer <your_jwt>.Server Protection: Protected endpoints in the FastAPI application will have a dependency that:
Extracts the token from the header.
Verifies the signature using the secret key.
Checks the claims (e.g., that the token hasn't expired).
If the token is valid, it processes the request. Otherwise, it returns a
401 Unauthorizederror.
Implementing JWT in FastAPI
Step 1: Install Dependencies
Step 2: Create a main.py
main.pyTesting the Application
You can test the application's endpoints using two popular tools: Swagger Docs and Postman. This section will guide you through the process for both.
Using Swagger
Execute the following command to run the program:
Then, visit the Swagger Docs at http://127.0.0.1:8080/docs and the result is as below figure.

Now, click the Authorize button on the right hand-side and enter the username/password as declared in the program, e.g., john.doe/mypassword , and click Authorize button. Once authorized, call the endpoint /users/me/ to get the expected response shown below:
Using Postman
The following video will show you how to test JWT in Postman.
Exercises
Q1. To understand the structure of a JWT and how its claims are tamper-proof without writing any backend code, you first generate an JWT string and the secret key used to sign it. Your task is to use the JWT.IO tool to decode it, inspect its contents, and understand what happens when you try to alter it.
Q2. Modify the JWT to include user roles (admin, user) and restrict access to specific endpoints based on these roles.
Hint:
Modify the Database: In the
fake_users_db, add aroleto each user. Create at least oneadminand oneuser.
Update Token Creation: Modify the
/tokenendpoint's logic. When you create the access token, add the user'sroleas a custom claim in the payload.
Create a Dependency for Admins: Create a new dependency function called
get_current_admin_user. This function should reuseget_current_active_userbut add an extra check. It must verify that theroleclaim in the token's payload is exactly"admin". If not, it should raise anHTTPExceptionwith astatus_codeof403 Forbiddenand a detail message like "Admin privileges required".Create the Protected Endpoint: Create a new endpoint
GET /admin/dashboardthat depends onget_current_admin_user. If successful, it should return a message like{"message": "Welcome to the admin dashboard, {username}!"}.
Last updated