How I Secured My ASP.NET Core APIs Using JWT and [Authorize] (Real-World Guide)
When building modern applications, security is something you cannot ignore.
How I Secured My ASP.NET Core APIs Using JWT and [Authorize] (Real-World Guide)
When building modern applications, security is something you cannot ignore.
Recently, I worked on an ASP.NET Core Web API consumed by a frontend application. Functionally, everything worked perfectly — but there was one major concern:
Anyone who knew the API URL could potentially access endpoints through Postman, Swagger, or any HTTP client.
That’s when I decided to implement JWT (JSON Web Token) authentication along with ASP.NET Core’s **[Authorize] attribute. Later, I also integrated the solution with Kong API Gateway** to add another layer of security.
In this article, I’ll share:
- Why I chose JWT authentication
- When JWT is the right choice
- How
[Authorize]protects APIs - A real mistake I made with Kong Gateway (and what I learned from it)
The Problem
My application’s architecture looked like this:
- React/Angular frontend
- ASP.NET Core Web API backend
- Publicly exposed API endpoints
- No authentication or authorization
This created several security risks:
- Sensitive data could be accessed by unauthorized users
- No identity verification
- No access control
- Increased attack surface
Although the application worked, it wasn’t secure.
The Solution: JWT Authentication
I needed an authentication mechanism that was:
- Easy to implement
- Scalable
- Stateless
- Suitable for modern web and mobile applications
JWT (JSON Web Token) turned out to be the perfect fit.
How JWT Works (In Simple Terms)
The authentication flow is straightforward:
- User logs in.
- Server verifies the user’s credentials.
- Server generates a JWT token.
- Client stores the token.
- Client sends the token with every request.
- Server validates the token before processing the request.
Once validated, the API knows exactly who the user is and whether they should be granted access.
Implementing JWT in ASP.NET Core
Example code to Configure JWT in Program.cs
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = builder.Configuration["JwtSettings:Issuer"],
ValidAudience = builder.Configuration["JwtSettings:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(builder.Configuration["JwtSettings:Key"])),
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true
};
});
Note: Always enable ValidateLifetime in production to prevent expired tokens from being accepted.
Don’t forget to add before mapping controllers.:
app.UseAuthentication();
app.UseAuthorization();
Real Scenario: Employee Portal System
Imagine you’re developing an Employee Portal where users can:
- View their profile
- Access salary information
- Download reports
- Submit requests
Only authenticated employees should be able to access this data.
Your JWT settings might look like this:
"JwtSettings": {
"Issuer": "https://auth.mycompany.com",
"Audience": "employee-api",
"Key": "MySuperSecretKey123"
}
Understanding Key Concepts
1. Issuer → Who Created the Token?
"Issuer": "https://auth.mycompany.com"
The issuer identifies the authority that generated the token.
In this case:
- Employees authenticate through
auth.mycompany.com - That server issues JWT tokens
- APIs trust tokens generated by this issuer
Real-world analogy:
Think of it like: Passport issuing authority “Government of India issued this passport”. Similarly, your API trusts tokens issued by your authentication server.
What happens during validation?
ValidateIssuer = true
API checks: “Did this token come from auth.mycompany.com?”
Yes → allow No → reject
2. Audience → Who Should Use the Token?
"Audience": "employee-api" //Sometimes its a client id of an app
Many organizations have multiple applications and APIs:
- employee-api
- payroll-api
- admin-api
This token is only for: employee-api
Real-life analogy:
You get an ID card for a specific building:
Office Building A → accept Office Building B → reject
You cannot use the same card everywhere
ValidateAudience = true
API checks: “Is this token meant for me?”
Yes → allow No → reject
3. Signing Key — How Do We Know the Token Wasn’t Modified?
"Key": "MySuperSecretKey123"
- Token is digitally signed using this key
- API uses the same key to verify
👉 This ensures: Token was not modified
Real-life analogy:
Think of it like: A sealed envelope with a signature stamp
If seal is broken → reject If seal matches → accept
Validation:
ValidateIssuerSigningKey = true
API verifies: “Is this token original and not tampered?”
4. Token Expiry (Lifetime)
ValidateLifetime = true
- Token valid for 1 hour
- After that → expired
Real-life analogy:
Movie ticket — Valid for 3 PM show At 6 PM → invalid
API checks: “Is token still valid?”
Complete Authentication Flow
Here’s how everything works together:
Step 1: User Logs In
The authentication server generates a token:
{
"iss": "https://auth.mycompany.com",
"aud": "employee-api",
"sub": "12345",
"role": "Employee"
}
Step 2: Frontend Sends Request
GET /api/profile
Authorization: Bearer <token>
Step 3: API Validates the Token
The API checks:
- Issuer matches
- Audience matches
- Signature is valid
- Token is not expired
If all validations pass:
Access is granted.
The Power of [Authorize]
Once JWT authentication is configured, protecting endpoints becomes incredibly simple.
[Authorize]
[HttpGet("secure-data")]
public IActionResult GetSecureData()
{
return Ok("This is protected data.");
}
The [Authorize] attribute automatically:
- Verifies authentication
- Validates the JWT token
- Blocks anonymous requests
- Prevents unauthorized access
For me, adding [Authorize] was the moment the API truly became secure.
Final Thoughts
Implementing JWT authentication and ASP.NET Core’s [Authorize] attribute significantly improved the security of my APIs. The setup was relatively simple, highly scalable, and perfectly suited for modern web applications.
The biggest lesson I learned was that authentication alone isn’t enough. A secure API design should include multiple layers of protection — from API gateways to backend authorization checks.
If you’re building ASP.NET Core APIs that are consumed by React, Angular, mobile apps, or microservices, JWT authentication combined with [Authorize] is one of the most effective security approaches you can adopt.
메타데이터
- post_id
- b46f2bda1721
- slug
- how-i-secured-my-asp-net-core-apis-using-jwt-and-authorize-real-world-guide-b46f2bda1721
- url
- https://medium.com/@chandjogani93/how-i-secured-my-asp-net-core-apis-using-jwt-and-authorize-real-world-guide-b46f2bda1721
- canonical_url
- https://medium.com/@chandjogani93/how-i-secured-my-asp-net-core-apis-using-jwt-and-authorize-real-world-guide-b46f2bda1721
- author_url
- https://medium.com/@chandjogani93
- status
- ok
- fetched_at
- 2026-07-15 16:48:10