In this blog post, we’ll walk through the process of implementing JWT (JSON Web Token) authentication in a .NET Core 8 Web API. We’ll also configure Swagger to support JWT authentication for testing and demonstrate how to use Postman for end-to-end testing.
What is JWT?
JSON Web Token (JWT) is a compact, self-contained token used for securely transmitting information between parties. It is widely used for authentication and authorization in web applications. JWTs consist of three parts: the header, the payload, and the signature.
- Header: Contains metadata about the token, including the signing algorithm.
- Payload: Contains claims or statements about the user and additional data.
- Signature: Ensures the token’s integrity and authenticity by combining the encoded header, payload, and a secret key.
Example JWT:
eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJzdWIiOiAiMTIzNDU2Nzg5MCIsICJuYW1lIjogIkpvaG4gRG9lIiwgImlhdCI6IDE1MTYyMzkwMjJ9.V7FQ7sCw3W8A-VzAWMjY6OhlAtCO7R7Xlwk4qxKdkFo
Step 1: Create a New .NET Core 8 Web API Project
Open your terminal or command prompt and run the following command to create a new .NET Core 8 Web API project:
dotnet new webapi -n JwtAuthDemo
cd JwtAuthDemo
Open the project in your preferred IDE (e.g., Visual Studio, Visual Studio Code).
Step 2: Install Required NuGet Packages
You need to install the Microsoft.AspNetCore.Authentication.JwtBearer
package. Run the following command in the terminal:
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
Step 3: Configure JWT Authentication and Swagger for Secure API Access
Open Program.cs
and configure JWT authentication:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Configure JWT Authentication
var key = Encoding.ASCII.GetBytes("ThisIsASecretKeyThatIsAtLeast32CharactersLong!");
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
// Configure Swagger
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "JwtAuthDemo", Version = "v1" });
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Name = "Authorization",
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer",
BearerFormat = "JWT",
In = ParameterLocation.Header,
Description = "Enter 'Bearer' [space] and then your valid token in the text input below.\r\n\r\nExample: \"Bearer 12345abcdef\""
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[] {}
}
});
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "JwtAuthDemo v1");
});
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Step 4: Create an Authentication Controller
Create a new file Controllers/AuthController.cs
:
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
namespace JwtAuthDemo.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class AuthController : ControllerBase
{
[HttpPost("login")]
public IActionResult Login([FromBody] UserLogin userLogin)
{
if (userLogin == null || userLogin.Username != "testuser" || userLogin.Password != "password")
{
return Unauthorized();
}
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes("ThisIsASecretKeyThatIsAtLeast32CharactersLong!");
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.Name, userLogin.Username)
}),
Expires = DateTime.UtcNow.AddHours(1),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var tokenString = tokenHandler.WriteToken(token);
return Ok(new { Token = tokenString });
}
}
public class UserLogin
{
public string Username { get; set; }
public string Password { get; set; }
}
}
Step 5: Protect an Endpoint with JWT
Create a new file Controllers/WeatherForecastController.cs
:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace JwtAuthDemo.Controllers
{
[Authorize]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public string? Summary { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
}
Step 6: Test JWT Authentication in Swagger
Run the application:
dotnet run
Open Swagger UI by navigating to https://localhost:5001/swagger
(or the appropriate URL for your application).
To retrieve a JWT token, send a POST request to /api/auth/login
with the following JSON body:
{
"username": "testuser",
"password": "password"
}
Authorize with JWT:
- Click on the “Authorize” button.
- Enter the JWT token in the format:
Bearer YOUR_TOKEN_HERE
. - Click “Authorize”.
Test the protected endpoint:
Use Swagger to test the GET /weatherforecast
endpoint with the authorization header set.
Step 7: Test JWT Authentication with Postman
Open Postman and create a new POST request to obtain the JWT token:
- URL:
https://localhost:5001/api/auth/login
- Method:
POST
- Body (raw JSON):
{
"username": "testuser",
"password": "password"
}
Send the request and copy the JWT token from the response.
Create a new GET request in Postman to test the protected endpoint:
- URL:
https://localhost:5001/weatherforecast
- Method:
GET
- Headers:
- Key:
Authorization
- Value:
Bearer YOUR_TOKEN_HERE
(replaceYOUR_TOKEN_HERE
with the token you obtained from the login request)
- Key:
- Send the request to verify that the endpoint is protected and returns the expected data.
Conclusion
In this blog post, we’ve covered how to implement JWT authentication in a .NET Core 8 Web API. We configured Swagger to handle JWT tokens and demonstrated how to test the authentication process using Postman. This setup ensures your API endpoints are secure and only accessible to authenticated users.
Feel free to use this guide to integrate JWT authentication into your .NET Core projects and test them effectively.
Thanks for reading! Cheers and happy coding!