Introduction
Authentication is one of the most important parts of any application. Whether you are building a web app, mobile app, or API, you need a secure way to verify users.
JWT (JSON Web Token) is a popular method used in modern applications for authentication. But JWT alone is not enough for long-term security. That’s where Refresh Tokens come in.
In this guide, we will understand JWT and Refresh Tokens in very simple words and learn how to implement them step by step in an ASP.NET Core application.
What is JWT?
JWT (JSON Web Token) is a compact, secure way to send information between client and server.
It contains:
When a user logs in, the server generates a JWT and sends it to the client.
The client then sends this token in every request.
In simple words:
JWT is like a digital identity card for the user.
Why Use JWT Authentication?
Stateless (no server-side session)
Fast and scalable
Works well with APIs and microservices
Easy to integrate with frontend apps
Problem with JWT (Important)
JWT tokens usually have an expiration time.
Example:
After expiry:
This creates poor user experience.
What is a Refresh Token?
A Refresh Token is a long-lived token used to generate new JWT tokens.
Flow:
In simple words:
Refresh Token helps users stay logged in without logging in again.
JWT vs Refresh Token
| Feature | JWT (Access Token) | Refresh Token |
|---|
| Purpose | Access API | Generate new JWT |
| Lifetime | Short | Long |
| Storage | Client | Secure storage |
Step-by-Step: Implement JWT Authentication in ASP.NET Core
Step 1: Create a .NET Project
dotnet new webapi -n JwtAuthDemo
cd JwtAuthDemo
Step 2: Install Required Packages
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
Step 3: Configure JWT in appsettings.json
{
"Jwt": {
"Key": "ThisIsVerySecretKey12345",
"Issuer": "yourapp",
"Audience": "yourapp"
}
}
Step 4: Configure Authentication in Program.cs
builder.Services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "yourapp",
ValidAudience = "yourapp",
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes("ThisIsVerySecretKey12345"))
};
});
builder.Services.AddAuthorization();
Step 5: Generate JWT Token
public string GenerateToken(string username)
{
var claims = new[]
{
new Claim(ClaimTypes.Name, username)
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("ThisIsVerySecretKey12345"));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: "yourapp",
audience: "yourapp",
claims: claims,
expires: DateTime.Now.AddMinutes(15),
signingCredentials: creds);
return new JwtSecurityTokenHandler().WriteToken(token);
}
Step 6: Create Login API
[HttpPost("login")]
public IActionResult Login(string username)
{
var token = GenerateToken(username);
return Ok(new { token });
}
Step 7: Protect API with [Authorize]
[Authorize]
[HttpGet("secure")]
public IActionResult Secure()
{
return Ok("This is a protected API");
}
Step 8: Implement Refresh Token Logic
Create a model:
public class RefreshToken
{
public string Token { get; set; }
public DateTime ExpiryDate { get; set; }
}
Generate Refresh Token:
public string GenerateRefreshToken()
{
return Convert.ToBase64String(RandomNumberGenerator.GetBytes(64));
}
Step 9: Create Refresh Endpoint
[HttpPost("refresh")]
public IActionResult Refresh(string refreshToken)
{
// Validate refresh token (from DB)
var newAccessToken = GenerateToken("user");
return Ok(new { token = newAccessToken });
}
Step 10: Best Practices for JWT Authentication
Real-World Flow
User logs in
Server returns Access Token + Refresh Token
User calls APIs using Access Token
Token expires
Refresh Token generates new Access Token
Conclusion
JWT with Refresh Tokens provides a secure and scalable authentication system for ASP.NET Core applications. It improves user experience while maintaining strong security.
Start with basic JWT authentication, then enhance it with refresh tokens, secure storage, and token rotation to build production-ready systems.