Security has become one of the most important aspects of modern software development. Whether you are building a small application, a mobile backend, or an enterprise-level platform, protecting your APIs should never be considered optional. APIs frequently handle sensitive information such as user accounts, email addresses, authentication data, and private business information. Without proper security, unauthorized users could gain access to resources they should never see.
One of the most widely used methods for securing APIs today is JWT authentication. JWT stands for JSON Web Token, and it provides a secure and scalable method for authenticating users without storing session data on the server. JWT works extremely well with ASP.NET Core because it is lightweight and easily integrates with REST APIs.
In this tutorial, you will learn how to implement JWT authentication in C# step by step while creating a secure API in ASP.NET Core.
What Is JWT Authentication?
JWT, or JSON Web Token, is an industry standard method used to securely transfer information between two parties. Rather than storing session information on the server, the application sends a token back to the client after successful authentication. The client then includes that token in future requests.
JWT contains three sections:
Header
Contains information about token type and encryption algorithm.
Example:
{ "alg":"HS256", "typ":"JWT"}Payload
Contains user information and claims.
{ "Username":"john", "Role":"Admin"}Signature
The signature verifies that the token has not been modified.
JWT format:
Header.Payload.Signature
This approach allows the server to validate users without needing to maintain session state.
Why JWT Authentication Is Popular
JWT authentication has become one of the preferred methods for securing APIs because it offers multiple advantages.
Benefits include:
- Stateless authentication
- Faster application performance
- Easier scalability
- Works with mobile and web applications
- Supports role-based access control
- Reduces server-side storage requirements
Traditional session-based authentication stores user information on the server, while JWT authentication keeps the process lightweight and efficient.
Creating a New ASP.NET Core Project
Begin by creating a new ASP.NET Core API project.
Open your terminal and run:
dotnet new webapi -n JwtAuthenticationDemo
Navigate into the project directory:
cd JwtAuthenticationDemo
Run the application:
dotnet run
You now have a clean API project ready for authentication implementation.
Install JWT Authentication Package
ASP.NET Core requires JWT Bearer authentication packages.
Install the package using:
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
Or use Package Manager:
Install-Package Microsoft.AspNetCore.Authentication.JwtBearer
This package enables ASP.NET Core to create and validate JWT tokens automatically.
Create a User Model
Inside your project, create a Models folder and add the following class:
User.cs
namespace JwtAuthenticationDemo.Models{ public class User { public string Username { get; set; } public string Password { get; set; } }}This simple model will allow users to submit login credentials.
For production environments, remember these recommendations:
- Store users in SQL Server
- Hash passwords
- Use environment variables for secrets
- Implement role-based authorization
Example password hashing:
BCrypt.HashPassword(password);
Configure JWT Settings
Open your:
appsettings.json
Add:
{ "Jwt": { "Key":"YourSuperSecretKey12345", "Issuer":"JwtDemo", "Audience":"JwtUsers" }}Explanation:
Key
Used to sign and validate tokens.
Issuer
Application generating the token.
Audience
Identifies who may use the token.
Configure Authentication in Program.cs
Open:
Program.cs
Add the following:
using Microsoft.AspNetCore.Authentication.JwtBearer;using Microsoft.IdentityModel.Tokens;using System.Text;var builder = WebApplication.CreateBuilder(args);builder.Services.AddControllers();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"])) };});builder.Services.AddAuthorization();var app=builder.Build();app.UseAuthentication();app.UseAuthorization();app.MapControllers();app.Run();This tells ASP.NET Core to:
- Enable JWT authentication
- Validate incoming tokens
- Reject invalid users
- Apply authorization rules
Create Authentication Controller
Create:
AuthController.cs
Add:
using Microsoft.AspNetCore.Mvc;using Microsoft.IdentityModel.Tokens;using System.IdentityModel.Tokens.Jwt;using System.Security.Claims;using System.Text;[ApiController][Route("[controller]")]public class AuthController : ControllerBase{ [HttpPost("login")] public IActionResult Login() { var claims=new[] { new Claim( ClaimTypes.Name, "admin") }; var key= new SymmetricSecurityKey( Encoding.UTF8.GetBytes( "YourSecretKey")); var credentials= new SigningCredentials( key, SecurityAlgorithms.HmacSha256); var token= new JwtSecurityToken( claims:claims, expires: DateTime.Now.AddMinutes(30), signingCredentials: credentials); return Ok( new JwtSecurityTokenHandler() .WriteToken(token)); }}This controller creates a JWT token after successful authentication.
Secure API Endpoints
Now create:
SecureController.cs
Add:
using Microsoft.AspNetCore.Authorization;using Microsoft.AspNetCore.Mvc;[ApiController][Route("[controller]")]public class SecureController : ControllerBase{ [Authorize] [HttpGet] public IActionResult Get() { return Ok( "Authenticated User"); }}The [Authorize] attribute automatically blocks users who do not have valid tokens.
Only authenticated users can access this endpoint.
Testing JWT Authentication Using Swagger
Run your application:
dotnet run
Open Swagger:
https://localhost:5001/swagger
Call:
POST /Auth/login
Example request:
{ "username":"admin", "password":"password"}Response:
{ "token":"eyJhbGciOi..."}Copy the token.
Select:
Authorize
Add:
Bearer YOUR_TOKEN
You should now have access to secure endpoints.
Security Best Practices For Secure APIs
JWT authentication is powerful, but developers sometimes introduce security risks accidentally.
Avoid these common mistakes.
Using weak secret keys
Bad example:
123456
Better example:
Jf@92Kj!83xQ9P#1
Storing passwords in plain text
Always hash passwords:
BCrypt.HashPassword(password);
Ignoring token expiration
Example:
DateTime.Now.AddMinutes(30)
Using HTTP instead of HTTPS
Always use HTTPS for production APIs.
Continue Expanding Your Development Skills
If you want to improve your ASP.NET Core and security knowledge further, consider learning:
Secure File Upload Validation in ASP.NET Core
Learn how file upload vulnerabilities occur and how to prevent them.
Repository Pattern in C#
Build cleaner and more maintainable application architectures.
Role-Based Authorization in ASP.NET Core
Expand JWT functionality by adding Admin and User permissions.
SQL Server Performance Optimization
Improve query speed and overall application performance.
These topics naturally complement secure API development and can help strengthen your applications.
Helpful Resources
Official JWT documentation:
Microsoft ASP.NET Core Security:
ASP.NET Core Security Documentation
OWASP secure coding guide:
Final Thoughts
JWT authentication remains one of the most effective ways to secure modern APIs. It provides a scalable, flexible, and efficient authentication solution for web applications and cloud-based systems.
Understanding JWT authentication in C# gives developers a strong foundation in API security and prepares them for more advanced concepts such as refresh tokens, role-based permissions, identity frameworks, and multi-factor authentication.
Implementing secure authentication early in development can save significant time and reduce security risks later.
Want to learn how to improve password security? Click here for more details.




