JWT (JSON Web Token) authentication in ASP.NET Core API is a secure and efficient way to handle user authentication and authorization. Here's a step-by-step article on setting up JWT authentication in an ASP.NET Core Web API.
Install Required NuGet Packages
Configure JWT Authentication
Update Program.cs to configure JWT authentication in the service section and middleware section.
builder.Services.AddAuthentication(opt =>
{
opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(opt =>
{ // for development only
opt.RequireHttpsMetadata = false;
opt.SaveToken = true;
opt.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(builder.Configuration["JWT:SecretKey"])),
ValidateIssuer = true,
ValidIssuer = builder.Configuration["JWT:Issuer"],
ValidateAudience = true,
ValidAudience = builder.Configuration["JWT:Audience"]
};
});
builder.Services.AddAuthorization();
var app = builder.Build();
// Use authentication and authorization
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
This configuration sets up the application to authenticate incoming requests using the JWT tokens and validate them based on certain parameters.
Generate the JWT Tokens
public string GenerateJwtToken(string userName, string name, string role)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_configuration["JWT:SecretKey"]);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.Name, userName),
new Claim(ClaimTypes.GivenName, name),
new Claim(ClaimTypes.Role, role)
}),
IssuedAt = DateTime.UtcNow,
Issuer = _configuration["JWT:Issuer"],
Audience = _configuration["JWT:Audience"],
Expires = DateTime.UtcNow.AddMinutes(30), // can change exprires time
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature),
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var userToken = tokenHandler.WriteToken(token);
return userToken;
}
Authenticate Users And Issue The JWT Tokens
[HttpPost("login")]
public IActionResult Login(LoginModel model)
{
// Authenticate user
var user = _userService.Authenticate(model.Username, model.Password);
if (user == null)
return Unauthorized();
// Generate JWT token
var token = _authenticationService.GenerateJwtToken(
user.userName,
user.Name,
user.Role
);
return Ok(new { token });
}
Secure Your API Endpoints
Add the [Authorize] attribute to protect API endpoints. Example.
[ApiController]
[Route("api/[controller]")]
public class ProtectedController : ControllerBase
{
[HttpGet]
[Authorize]
public IActionResult GetSecureData()
{
return Ok(new { Message = "This is a secure endpoint." });
}
}
Test Your .NET JWT Authentication
- Use a tool like Postman or cURL to test the endpoints.
- First, call the /api/auth/login endpoint with valid credentials to get a token.
- Use the token in the Authorization header of subsequent requests to protected endpoints:
Authorization: Bearer <your-jwt-token>
JWT token part
A JWT (JSON Web Token) consists of three parts, separated by dots (.): Header, Payload, and Signature. Here's a breakdown of these parts.
Header
The header typically consists of two fields.
- alg: The signing algorithm used (e.g., HS256 for HMAC-SHA256).
- typ: The type of the token, usually JWT.
{
"alg": "HS256",
"typ": "JWT"
}
Payload
The payload contains the claims. Claims are statements about the user or additional data. There are three types of claims.
- Registered claims: Predefined claims like iss (issuer), exp (expiration), sub (subject), and aud (audience).
- Public claims: Custom claims defined for specific use cases.
- Private claims: Claims shared between parties that agree on them.
{
"sub": "1234567890",
"name": "dashrath",
"role": "Admin",
"iat": 1672545600,
"exp": 1672549200
}
Signature
The signature is used to verify the authenticity of the token and ensure that it hasn’t been tampered with.
The signature is created by,
- Taking the encoded header and payload.
- Concatenating them with a dot (.).
- Hashing the result using the specified algorithm and a secret key.
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret_key
)
Final Token format
The JWT token is the concatenation of these three parts.
<base64UrlEncodedHeader>.<base64UrlEncodedPayload>.<base64UrlEncodedSignature>
Example
JWT: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwicm9sZSI6IkFkbWluIiwiaWF0IjoxNjcyNTQ1NjAwLCJleHAiOjE2NzI1NDkyMDB9.DjKU_JB_b9PxwjU_x5U3wwtrLX7ZnZZ0mKXfTi5YYCU
Conclusion
In the end, we can conclude that Authentication and Authorization in .NET Core are crucial to the security and safety of your application, and implementing JWT authentication in .NET Core allows a robust and secure solution for authenticating your users and protecting the resources in web applications. Through the integration of JWT authentication, .NET Core applications can achieve scalability, flexibility, and interoperability, ensuring a seamless user experience while prioritizing data integrity and confidentiality. As technology continues to evolve, embracing .NET JWT authentication in .NET Core remains a pivotal strategy for safeguarding sensitive information and fortifying the integrity of modern web applications.