In the previous article, we successfully generated a JWT and returned it to the client after login. At this point, the client has an access token that represents the authenticated user.
But there's one important question:
How does the API know whether the received token is genuine or fake?
Simply receiving a JWT does not mean the API should trust it. Anyone can copy a token, modify it, or even create a fake one. Before executing a protected endpoint, ASP.NET Core must validate the token and ensure it was issued by a trusted source.
In this article, you'll learn how JWT validation works internally and how to configure JWT Bearer Authentication in an ASP.NET Core Web API.

What Is JWT Validation?
JWT validation is the process of verifying whether an incoming token is authentic, valid, and trustworthy before allowing access to a protected API.
Think of a movie ticket.
When you enter a cinema, the security staff doesn't just check whether you're holding a ticket. They verify:
Is the ticket genuine?
Has it expired?
Is it for this theatre?
Has it been tampered with?
Only after these checks are completed are you allowed to enter.
JWT validation follows exactly the same idea.
Why Is Token Validation Necessary?
Suppose someone sends the following request:
GET /api/orders
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...The API cannot simply trust this token because:
The token may have expired.
Someone may have modified its contents.
It may have been issued by another application.
It may have been created using an invalid signing key.
Without validation, anyone could gain unauthorized access to your APIs.
How JWT Validation Works
Whenever a protected endpoint receives a request, ASP.NET Core automatically performs several validation steps.
HTTP Request
│
▼
Read Authorization Header
│
▼
Extract JWT
│
▼
Validate Token
│
├── Signature
├── Expiration
├── Issuer
├── Audience
│
▼
Create User Identity
│
▼
Execute ControllerIf any validation fails, the request stops immediately.
The controller action is never executed.
Step 1: Install JWT Bearer Authentication
If you haven't already installed the package, run:
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearerThis package provides the middleware responsible for reading and validating JWT tokens.
Step 2: Register JWT Authentication
Open Program.cs.
Add the required namespaces.
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;Now register JWT authentication.
builder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters =
new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey =
new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(
builder.Configuration["Jwt:Key"]!))
};
});This tells ASP.NET Core how every incoming JWT should be validated.
Understanding TokenValidationParameters
This class contains all the validation rules.
Let's understand each property.
ValidateIssuer
ValidateIssuer = trueThis verifies that the token was generated by the expected application.
If another application creates a token, ASP.NET Core rejects it.
ValidateAudience
ValidateAudience = trueEvery JWT is created for a particular audience.
This check ensures the token belongs to your application.
ValidateLifetime
ValidateLifetime = trueEvery JWT has an expiration time.
If the token has expired, the request is rejected.
Expired tokens should never be accepted.
ValidateIssuerSigningKey
ValidateIssuerSigningKey = trueThis is one of the most important checks.
ASP.NET Core verifies the digital signature using the secret signing key.
If someone modifies even one character inside the token, validation fails.
IssuerSigningKey
IssuerSigningKey =
new SymmetricSecurityKey(...)This is the same secret key that was used when generating the JWT.
If the signing key doesn't match, the token cannot be trusted.
Step 3: Enable Authentication Middleware
Registering authentication services is not enough.
The middleware must also be added to the request pipeline.
app.UseAuthentication();
app.UseAuthorization();The order is extremely important.
Authentication must always execute before authorization.
Otherwise, ASP.NET Core won't know who the current user is.
Internal Request Flow
Now let's see what actually happens when a request reaches the API.
Client
│
│ Bearer Token
▼
Authentication Middleware
│
▼
Read Authorization Header
│
▼
Extract JWT
│
▼
Validate Signature
│
▼
Validate Expiration
│
▼
Validate Issuer
│
▼
Validate Audience
│
▼
Authenticated User Created
│
▼
Authorization Middleware
│
▼
Controller ActionNotice something important.
Your controller never validates the JWT manually.
ASP.NET Core completes all validation before your controller is executed.
Practical Example
Let's continue with the SecureShop API.
A customer sends the following request:
GET /api/orders
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...ASP.NET Core performs these checks:
Is the Authorization header present?
Is the JWT correctly formatted?
Is the signature valid?
Has the token expired?
Was it issued by SecureShop?
Is it intended for this API?
If all answers are Yes, the request continues.
Otherwise, the API immediately returns:
401 UnauthorizedThe controller action is never called.
What Happens After Successful Validation?
Once validation succeeds, ASP.NET Core creates an authenticated user internally.
Conceptually, the flow becomes:
JWT
│
▼
Claims
│
▼
Claims Identity
│
▼
Claims Principal
│
▼
HttpContext.UserFrom this point onward, your controllers can access the logged-in user's information using:
User.Identityor
User.ClaimsWe'll use these in upcoming articles when protecting endpoints.
Common Mistakes
Mistake 1: Forgetting UseAuthentication()
Some developers configure JWT authentication but forget to add:
app.UseAuthentication();Without this middleware, ASP.NET Core never validates incoming tokens.
Mistake 2: Incorrect Middleware Order
This is incorrect:
app.UseAuthorization();
app.UseAuthentication();Always write:
app.UseAuthentication();
app.UseAuthorization();Authentication identifies the user.
Authorization decides whether the identified user has permission to access the resource.
Mistake 3: Using Different Secret Keys
The secret key used to generate the JWT must be the same key used during validation.
If the keys differ, every request will fail validation.
Mistake 4: Disabling Validation Checks
Some beginners write:
ValidateLifetime = false;or
ValidateIssuer = false;This may make testing easier, but it significantly reduces security.
In production, always enable the required validation checks.
Key Takeaways
Receiving a JWT does not mean the API should trust it.
ASP.NET Core validates every incoming token before executing protected endpoints.
The framework checks the signature, expiration time, issuer, audience, and signing key.
JWT validation is handled automatically by the JWT Bearer Authentication Middleware.
Authentication middleware must be added before authorization middleware.
After successful validation, ASP.NET Core creates an authenticated user that your application can access.
Now our API can generate JWTs and validate incoming tokens. The next step is to protect API endpoints using [Authorize], allowing only authenticated users to access specific resources while keeping other endpoints public.

Join the conversation! Your thoughts help the community grow.