Skip to main content
Most real APIs need to know who is making a request and whether they’re allowed to do what they’re asking. This lesson implements a complete, production-ready authentication system using JSON Web Tokens (JWT) — the recommended approach for stateless REST APIs. You’ll build user registration and login endpoints, token generation with expiry, a get_current_user dependency that protects routes, and role-based access control (RBAC) that restricts specific endpoints to admin users. Every piece follows the pattern used in production FastAPI applications.

Authentication Models Compared


What is a JWT?

A JSON Web Token is a compact, URL-safe string containing signed claims (statements about a user) that the server can verify without querying a database. A JWT has three dot-separated parts:
  1. Header — algorithm (HS256) and token type (JWT), Base64URL-encoded.
  2. Payload — claims: sub (subject/user ID), exp (expiry), role, and any other data you include.
  3. SignatureHMAC(base64(header) + "." + base64(payload), SECRET_KEY). Any change to the header or payload invalidates the signature.
The payload is only Base64URL-encoded, not encrypted. Anyone who has the token can decode and read the payload. Never store passwords, credit card numbers, or other sensitive data inside a JWT payload.

JWT Authentication Lifecycle


Step-by-Step Implementation

Step 1: Install Dependencies


Step 2: User Model


Step 3: Password Hashing

Never store plain-text passwords. Use bcrypt to hash on registration and verify at login:

Step 4: Token Generation

In production, load SECRET_KEY from an environment variable using os.getenv("SECRET_KEY") or a Pydantic BaseSettings class. Never commit secrets to version control.

Step 5: Registration and Login Endpoints


Step 6: Bearer Token Verification Dependency

This dependency extracts the JWT from the Authorization: Bearer <token> header, verifies its signature and expiry, and returns the authenticated user:

Step 7: Protecting Routes

Apply get_current_user to any endpoint that requires authentication:

Step 8: Role-Based Access Control (RBAC)

Use a dependency factory to restrict endpoints to specific roles:
Apply role requirements directly in the route decorator:

Testing in Swagger UI

1

Open Swagger UI

Navigate to http://127.0.0.1:8000/docs.
2

Register a user

Use POST /auth/register to create a test user.
3

Log in and copy the token

Use POST /auth/login with your credentials. Copy the access_token value from the JSON response.
4

Authorise in Swagger

Click the green Authorize 🔒 button at the top of the page. Paste your token in the value field and click Authorize.
5

Call protected endpoints

Now call /profile or any protected route — Swagger will automatically include the Authorization: Bearer <token> header.

Summary