Lesson Complete!
Protect Your Endpoints
What you built
Every expense endpoint now requires a valid JWT token. Each endpoint uses CurrentUser — a type alias for Annotated[User, Depends(get_current_user)] — to enforce authentication. You made three types of changes:
- Create: sets
expense.user_idto the current user's identifier before saving - List and summary: filter queries with
.where(Expense.user_id == current_user.id)so each user sees only their own data - Get, update, and delete: check
expense.user_id != current_user.idand return 404 if the expense belongs to a different user
Authentication vs. authorization
This lesson covers authentication — proving who you are. Every request must include a valid token, and the server identifies the user from that token.
Authorization is a separate concern — what a specific user is allowed to do. For example, an admin user who can view all expenses would require authorization rules. Your API does not have authorization yet, but the pattern is similar: add another dependency that checks the user's role or permissions before the endpoint runs.
What comes next
Your existing tests are all broken. They send requests without tokens, so every test gets a 401 error. Lesson 4 updates the test suite to register a user, log in, and include the token in every request.