Introduction
In this hands-on guide, you’ll learn how to build a RESTful Web API in ASP.NET MVC using C# with JWT (JSON Web Token) Authentication. This is a modern and secure method for handling user authentication and protecting your endpoints.
By the end of this tutorial, you’ll be able to.
- Generate JWT tokens on login
- Authenticate API calls using tokens
- Secure endpoints so only logged-in users can access them
Tools Required
- Visual Studio 2019/2022
- .NET Framework (4.7 or later)
- NuGet Package: System.IdentityModel.Tokens.Jwt
Step 1. Create a New ASP.NET Web API Project
- Open Visual Studio
- File → New → Project
- Select ASP.NET Web Application (.NET Framework)
- Name it JwtStudentAPI
- Choose the Web API template and click Create
Step 2. Install Required NuGet Package
Open the Package Manager Console and run.
Install-Package System.IdentityModel.Tokens.Jwt
Step 3. Create Student Model
File: Models/Student.cs.
using System;
namespace JwtStudentAPI.Models
{
public class Student
{
public string StudentId { get; set; }
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
public string ZipCode { get; set; }
public string Major { get; set; }
}
}
Step 4. Create Login Model
File: Models/UserCredential.cs.
namespace JwtStudentAPI.Models
{
public class UserCredential
{
public string Username { get; set; }
public string Password { get; set; }
}
}
This is a simple model for a login payload.
Step 5. Add Token Generation Logic
File: Controllers/AuthController.cs.
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Web.Http;
using JwtStudentAPI.Models;
using Microsoft.IdentityModel.Tokens;
namespace JwtStudentAPI.Controllers
{
public class AuthController : ApiController
{
[HttpPost]
[Route("api/auth/login")]
public IHttpActionResult Login(UserCredential login)
{
if (login.Username == "admin" && login.Password == "pass123")
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes("MySuperSecretKey12345");
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, login.Username)
}),
Expires = DateTime.UtcNow.AddMinutes(30),
SigningCredentials = new SigningCredentials(
new SymmetricSecurityKey(key),
SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var tokenString = tokenHandler.WriteToken(token);
return Ok(new { token = tokenString });
}
return Unauthorized();
}
}
}
Explanation
- Validates the hardcoded user (for demo).
- Generates a JWT using a secret key.
- Returns the token to the client.
Step 6. Create a Token Validation Handler
File: Handlers/JwtValidationHandler.cs.
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using Microsoft.IdentityModel.Tokens;
namespace JwtStudentAPI.Handlers
{
public class JwtValidationHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (!request.Headers.Contains("Authorization"))
return await base.SendAsync(request, cancellationToken);
var token = request.Headers.Authorization?.Parameter;
if (token == null)
return request.CreateResponse(HttpStatusCode.Unauthorized, "Missing token");
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes("MySuperSecretKey12345");
try
{
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
}, out SecurityToken validatedToken);
var jwtToken = (JwtSecurityToken)validatedToken;
var identity = new ClaimsIdentity(jwtToken.Claims, "jwt");
Thread.CurrentPrincipal = new ClaimsPrincipal(identity);
}
catch
{
return request.CreateResponse(HttpStatusCode.Unauthorized, "Invalid token");
}
return await base.SendAsync(request, cancellationToken);
}
}
}
Step 7. Register the JWT Handler
In Global.asax.cs, add this in Application_Start().
GlobalConfiguration.Configuration.MessageHandlers.Add(
new JwtStudentAPI.Handlers.JwtValidationHandler()
);
Step 8. Create a Protected Student Controller
File: Controllers/StudentController.cs.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using JwtStudentAPI.Models;
namespace JwtStudentAPI.Controllers
{
[Authorize]
public class StudentController : ApiController
{
private static List<Student> students = new List<Student>
{
new Student
{
StudentId = "S201",
Name = "Arun Kumar",
DateOfBirth = new DateTime(2000, 5, 15),
ZipCode = "600001",
Major = "IT"
},
new Student
{
StudentId = "S202",
Name = "Divya S",
DateOfBirth = new DateTime(2001, 3, 20),
ZipCode = "641002",
Major = "ECE"
}
};
[HttpGet]
[Route("api/student/{id}")]
public IHttpActionResult Get(string id)
{
var student = students.FirstOrDefault(s => s.StudentId.Equals(id, StringComparison.OrdinalIgnoreCase));
if (student == null)
return NotFound();
return Ok(student);
}
}
}
Step 9. Test Your API
1. Get Token
2. Access Protected API
- GET to: http://localhost:[PORT]/api/student/S202
- Header: Authorization: Bearer [token]
Summary
You have now built a complete JWT-authenticated ASP.NET Web API. You’ve learned how to:
- Generate a JWT token
- Validate incoming tokens
- Protect endpoints with [Authorize]
This is a scalable and secure authentication approach widely used in production systems.
Next Steps
- Store credentials and keys in secure settings (config or environment variables)
- Implement user registration and token refresh
- Use HTTPS in all requests
- Connect to a real database for dynamic user validation
Hands-On Ideas
- Add role-based access (e.g., Admin vs Student)
- Track token expiration
- Add logout functionality
- Test using Postman and Swagger
Happy coding with secure APIs! 🚀 Please do comment your questions, which can help to learn better!
Happy learning