Authentication & JWT
How Zomato knows it's YOU ordering pizza, not your neighbor. The #1 backend skill.
1. The Zomato Login Flow = JWT in Real Life
Step 1: Login once POST /api/auth/login with username + password.
Server replies: { "token": "eyJhbGci..." } This is your JWT - like a metro card.
Step 2: Every next request GET /api/orders + Header: Authorization: Bearer eyJhbGci...
Server checks: "Is this card valid? Is it expired? Is signature mine?" If yes โ 200 OK. If no โ 401.
๐ฏ Why Not Sessions?
Sessions: Server stores "User 5 is logged in" in RAM. 1 million users = server crashes. Can't scale.
JWT: Server stores NOTHING. All info is inside the token. Any server can validate it. Scales to billions.
2. JWT Anatomy - Crack It Open
JWT = xxxxx.yyyyy.zzzzz = Header.Payload.Signature
| Part | Example | Meaning |
|---|---|---|
| Header | eyJhbGci... | Algo used: HS256 |
| Payload | eyJzdWIi... | Your data: { "sub":"5", "role":"User", "exp": 1730000000 } |
| Signature | SflKxw... | Server's stamp. Proves token wasn't tampered. |
Key Point: Anyone can read Payload. It's Base64, not encrypted. Never put passwords in JWT. Put UserId, Role, Expiry only.
3. Code It: Secure Zomato API in 5 Mins
Step 1: Install + Configure Program.cs
builder.Services.AddAuthentication("Bearer")
.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(); // Who are you?
app.UseAuthorization(); // What can you do?
Step 2: appsettings.json
"Jwt": {
"Key": "ThisIsMySuperSecretKeyForZomato12345!", // 32+ chars
"Issuer": "ZomatoApi",
"Audience": "ZomatoApp",
"ExpiryMinutes": 60
}
Step 3: Login Endpoint - Generate Token
[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase {
[HttpPost("login")]
public IActionResult Login([FromBody] LoginDto dto) {
// 1. Check DB: is username/password correct?
if(dto.Username!= "admin" || dto.Password!= "123") return Unauthorized();
// 2. Create claims = data inside token
var claims = new[] {
new Claim(ClaimTypes.NameIdentifier, "5"),
new Claim(ClaimTypes.Role, "Admin")
};
// 3. Sign token
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: _config["Jwt:Issuer"],
audience: _config["Jwt:Audience"],
claims: claims,
expires: DateTime.Now.AddMinutes(60),
signingCredentials: creds);
return Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token) });
}
}
Step 4: Protect Endpoints
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase {
[HttpGet]
[Authorize] // Must have valid JWT
public IActionResult GetMyOrders() {
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
// Get orders for userId...
return Ok();
}
[HttpDelete("{id}")]
[Authorize(Roles = "Admin")] // Must be Admin
public IActionResult DeleteOrder(int id) {...}
}
app.UseAuthorization() before app.UseAuthentication(). Result: API always returns 401. Because it tries to check "what can you do" before knowing "who are you".
Order matters: Authentication first, Authorization second. Always.
No comments yet. Be the first to share your thoughts!