How Token Verification Works
Understand how your app will extract, decode, and validate tokens from incoming requests
What happens when a protected request arrives
Right now, your auth module can create tokens but has no way to check them. When a user sends a request with Authorization: Bearer eyJhbGc... in the header, your app needs to do three things:
- Extract the token from the
Authorizationheader - Decode the token using the same secret key that signed it
- Find the user in the database using the email stored inside the token
If any step fails — the header is missing, the token is expired, the signature is wrong, the user does not exist — the server returns a 401 "Unauthorized" response. The request never reaches your endpoint code.
FastAPI handles the header parsing for you
Parsing the Authorization header manually would mean reading the header, checking it starts with Bearer , splitting the string, and handling the case where the header is missing entirely. FastAPI provides a helper called OAuth2PasswordBearer that does all of this in one line.
You create it once as a variable:
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login")When FastAPI sees oauth2_scheme used as a dependency, it automatically reads the Authorization header, strips the Bearer prefix, and passes just the token string to your function. If the header is missing, it returns a 401 response before your code even runs. You never write a single line of header-parsing code.
The tokenUrl="login" parameter does not create an endpoint. It tells FastAPI's automatic documentation (Swagger UI) where to direct users to get a token. You will build the actual /login endpoint in Lesson 2.
Dependencies: functions that run before your endpoints
You have already used this pattern without knowing it. Every time you write session: SessionDep in an endpoint, FastAPI calls get_session() behind the scenes, creates a database session, and passes it to your function. You never call get_session() yourself — FastAPI handles it.
Token verification works the same way. You will write a function called get_current_user that takes a token and a database session, verifies the token, and returns the User object. In Lesson 3, you will add current_user: CurrentUser as a parameter to your endpoints, and FastAPI will call get_current_user automatically before each endpoint runs.
The pattern is Annotated[ReturnType, Depends(function)]. This tells FastAPI: "call this function and pass me the result." You describe WHAT you need, and FastAPI figures out HOW to provide it.
Why every error message says "Invalid token"
The verification function can fail for several reasons: the token expired, the signature was tampered with, the email is missing from the payload, or the user account was deleted. In every case, the error message is the same: "Invalid token".
This is intentional. If the server returned different messages for different failures — "token expired" versus "user not found" — an attacker could use those messages to learn about your system. A single vague message reveals nothing useful.