Authentication is at the core of almost every modern web application. Two popular approaches are Session-based authentication and JWT-based authentication. While both achieve the goal of verifying a user’s identity, they work in different ways, each with its own strengths and trade-offs.
Session-Based Authentication
Session-based authentication stores the user’s authentication data (usually a session ID) on the server after they log in. The client receives a cookie that contains this session ID. Every subsequent request includes this cookie, allowing the server to identify the user.
How it works (Step-by-Step):
-
User logs in → sends credentials (username/password) to server.
-
Server verifies credentials → creates a session object in memory or database.
-
Server generates a session ID → stores it in the session store and sends it back to the client in a cookie.
-
Client stores the cookie → automatically sends it with each HTTP request.
-
Server matches the session ID from the cookie to the stored session to identify the user.
Examples by using .Net Core (Session-based)
Startup.cs Configuration
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(30);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
app.UseRouting();
app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
Login Controller
[HttpPost]
public IActionResult Login(string username, string password)
{
if (username == "admin" && password == "secret")
{
HttpContext.Session.SetString("Username", username);
return RedirectToAction("Dashboard");
}
ViewBag.Error = "Invalid credentials";
return View();
}
Protected Dashboard
public IActionResult Dashboard()
{
var user = HttpContext.Session.GetString("Username");
if (string.IsNullOrEmpty(user))
return RedirectToAction("Login");
return View(model: $"Hello {user}");
}
Pros
- Simple to implement in MVC applications.
- Server-controlled session invalidation.
- Great for traditional web apps.
Cons
-
Requires server memory or distributed session store.
-
Harder to scale without central session storage.
JWT-Based Authentication
JWT (JSON Web Token) is a compact, self-contained token containing user identity and claims. It is signed by the server and sent to the client after successful authentication. Clients send the token in the Authorization
header for each request.
How it works (Step-by-Step):
- User logs in → sends credentials to server.
- Server validates credentials → generates a signed JWT.
- JWT is returned to client (usually stored in browser storage or mobile app memory).
- Client sends JWT in the
Authorization: Bearer <token>
header for each request. - Server validates the token signature on each request — no session storage needed.
.NET Core Example (JWT-based)
Install NuGet packages
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package System.IdentityModel.Tokens.Jwt
Startup.cs Configuration
public void ConfigureServices(IServiceCollection services)
{
var key = Encoding.ASCII.GetBytes("ThisIsASecretKeyForJWT");
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
services.AddControllers();
}
Login Controller (Generating JWT)
[HttpPost("login")]
public IActionResult Login([FromBody] LoginModel login)
{
if (login.Username == "admin" && login.Password == "secret")
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes("ThisIsASecretKeyForJWT");
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, login.Username) }),
Expires = DateTime.UtcNow.AddHours(1),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return Ok(new { Token = tokenHandler.WriteToken(token) });
}
return Unauthorized();
}
wt
Protected Endpoint
[Authorize]
[HttpGet("dashboard")]
public IActionResult Dashboard()
{
return Ok($"Hello {User.Identity.Name}");
}
Pros
- Stateless, no server-side session storage.
- Ideal for APIs and microservices.
- Works well across platforms and domains.
Cons
- Harder to revoke tokens before expiration.
- Larger payload size than a session ID.
- Must be secured to prevent token theft.
Key Differences b/w Session and JWT
Feature |
Session-Based |
JWT-Based |
---|---|---|
Storage Location |
Server-side |
Client-side |
Scalability |
Needs shared store |
Stateless, easy to scale |
Revocation |
Easy (delete session) |
Hard (needs blacklist) |
Best For |
Server-rendered apps |
APIs, mobile apps |
When to Use Which?
- Use Session-based authentication when:
- You have a traditional server-rendered app.
- You want quick and simple user authentication.
- You control the server environment (can store sessions centrally).
- Use JWT-based authentication when:
-
You’re building stateless APIs or microservices.
-
You need scalability and no central session store.
-
You’re serving multiple client types (web, mobile, IoT).
-
Example Scenario
Session Example: A company intranet web app stores user sessions in Redis so employees can log in from different offices without losing their session.
JWT Example: A mobile banking app sends a JWT to users after login. The backend API verifies the JWT for every request without storing any session, making it scalable across multiple load-balanced servers.