ASP.NET Core  

JWT Session 3: How JWT Authentication Flows Through an ASP.NET Core Web API

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.

  • Login is the identity verification.

  • JWT is the access card.

  • The API validates the access card before allowing entry.

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:

  • Who the user is

  • The user's role

  • The user's email

  • Other claims stored inside the token

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.