In the previous article, we learned that a JWT consists of three parts: Header, Payload, and Signature. We also saw that the payload contains user claims and the signature protects the token from being modified.
Now the next question is:
How does a JWT actually travel through an ASP.NET Core Web API?
Understanding this request flow is more important than memorizing code. Once you understand the lifecycle of a JWT, implementing authentication becomes much easier.
In this article, we'll follow the complete journey of a JWT—from the moment a user logs in until a protected API returns a successful response.
![JWT actually travel through an ASP.NET Core Web API]()
The JWT Authentication Flow?
JWT authentication is simply a sequence of steps that allows an API to identify a user without asking for their username and password on every request.
The entire process begins with login and continues until the user accesses protected resources.
The overall flow looks like this:
User Login
↓
Validate Credentials
↓
Generate JWT
↓
Return JWT to Client
↓
Store JWT
↓
Send JWT with API Request
↓
Validate JWT
↓
Create User Identity
↓
Execute Protected API
Every protected request follows this lifecycle.
Why Does This Flow Exist?
Imagine entering an office building.
On your first visit, the security desk checks your identity.
After verification, they issue you an employee access card.
Now, every time you enter the building, you simply scan the card.
The security guard doesn't ask for your government ID every single time.
JWT works in exactly the same way.
The user's password is required only during login.
Every request after that uses the JWT.
Step 1: User Logs In
Everything starts when the user submits their login credentials.
Example request:
POST /api/auth/login
{
"email": "[email protected]",
"password": "Password@123"
}
At this point, the API does not know who the user is.
Its first responsibility is to verify the provided credentials.
Step 2: API Validates the Credentials
The API searches for the user and verifies the password.
Conceptually, the process looks like this:
Receive Login Request
↓
Find User
↓
Verify Password
↓
Valid or Invalid?
Two outcomes are possible:
Invalid Credentials
If the email or password is incorrect, the login process stops.
401 Unauthorized
No JWT is generated.
Valid Credentials
If the credentials are correct, the user is successfully authenticated.
The API now knows the user's identity.
The next step is generating a JWT.
Step 3: API Generates a JWT
After successful authentication, the API creates a JWT.
Conceptually, the token contains information similar to this:
User Id
Name
Email
Role
Expiration Time
The API signs the token and returns it to the client.
Example response:
{
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"expiresIn": 1800
}
At this point, the login process is complete.
The API does not ask for the password again unless the user logs in again.
Step 4: Client Stores the JWT
The client receives the token and stores it.
The storage location depends on the type of application.
Examples include:
Angular application
React application
Mobile application
Desktop application
The important point is that the client keeps the JWT so it can be sent with future requests.
Step 5: Client Calls a Protected API
Suppose the user wants to view their profile.
The client sends a request like this:
GET /api/profile
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
The Authorization header contains the JWT.
The keyword Bearer tells the API that the request is carrying an access token.
Without this header, the API has no proof that the user is authenticated.
Step 6: ASP.NET Core Reads the Token
When the request reaches the ASP.NET Core Web API, authentication happens before the controller action executes.
The framework first checks whether an Authorization header exists.
HTTP Request
↓
Authorization Header Found?
↓
Yes / No
If no token is present, authentication fails.
If a token exists, ASP.NET Core starts validating it.
Step 7: Token Validation
The framework performs several security checks.
Conceptually, the validation process looks like this:
Read Token
↓
Validate Signature
↓
Validate Expiration
↓
Validate Issuer
↓
Validate Audience
↓
Token Valid?
Every check must pass.
If even one validation fails, the request is rejected.
The controller action never executes.
Step 8: Create the User Identity
If the JWT is valid, ASP.NET Core creates an authenticated user.
Internally, it builds an identity using the claims stored inside the token.
Conceptually:
JWT Claims
↓
Claims Identity
↓
Authenticated User
From this point onward, the API knows:
Controllers can use this identity without manually reading the JWT.
Step 9: Execute the Protected API
Only after successful authentication does ASP.NET Core execute the controller action.
Example:
GET /api/orders
If authentication succeeds:
200 OK
If authentication fails:
401 Unauthorized
This is why authentication happens before your controller logic.
Complete Internal Flow
Let's combine all the steps into one diagram.
Client
│
│ Login
▼
ASP.NET Core API
│
│ Validate Credentials
▼
Generate JWT
│
│ Return JWT
▼
Client Stores JWT
│
│ Bearer Token
▼
Protected API Request
│
▼
Authentication Middleware
│
│ Validate JWT
▼
Create User Identity
│
▼
Controller Action
│
▼
HTTP Response
This is the complete lifecycle of JWT authentication in an ASP.NET Core Web API.
Practical Example
Let's continue with our SecureShop API.
A customer wants to view their order history.
Login
POST /api/auth/login
The API validates the credentials and returns a JWT.
↓
View Orders
GET /api/orders
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
↓
The API validates the JWT.
↓
The customer is identified.
↓
The order data is returned.
Notice that the password was used only once during login.
Every request afterward depends entirely on the JWT.
Common Mistakes
Mistake 1: Sending the Password with Every Request
Some beginners think every API request should include the username and password.
This is incorrect.
The password is used only during authentication.
After login, the JWT becomes the user's identity for protected requests.
Mistake 2: Assuming the Controller Validates the JWT
Developers sometimes believe the controller checks whether the token is valid.
In reality, ASP.NET Core authentication middleware performs token validation before the request reaches the controller.
The controller receives only authenticated requests.
Mistake 3: Thinking Every Request Generates a New JWT
A JWT is created only after a successful login.
Subsequent API requests reuse the same token until it expires.
The API does not generate a new JWT for every request.
Key Takeaways
JWT authentication starts when a user logs in.
The API validates the user's credentials only once during login.
After successful authentication, the API generates a JWT.
The client sends the JWT with every protected request using the Authorization header.
ASP.NET Core validates the JWT before executing the controller.
If validation succeeds, an authenticated user identity is created.
If validation fails, the request is rejected before reaching your application logic.