Saturday, January 8, 2022

.NET 6 WebAPI with JWT bearer token authentication minimal example

The console client:
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

var plainTextSecurityKey = "This is secret";

var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(plainTextSecurityKey));
var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256Signature);

var claimsIdentity = 
    new ClaimsIdentity(new List<Claim>()
    {
        new Claim(JwtRegisteredClaimNames.Name, "username1")
    });

var securityTokenDescriptor = new SecurityTokenDescriptor()
{
    Subject = claimsIdentity,
    SigningCredentials = signingCredentials
};

var tokenHandler          = new JwtSecurityTokenHandler();
var plainToken            = tokenHandler.CreateToken(securityTokenDescriptor);
var signedAndEncodedToken = tokenHandler.WriteToken(plainToken);

Console.WriteLine(plainToken);
Console.WriteLine(signedAndEncodedToken);

HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {signedAndEncodedToken}");

var res = await client.GetAsync("http://localhost:5242/api/Example");
if (res.StatusCode == System.Net.HttpStatusCode.OK)
{
    var result = await res.Content.ReadAsStringAsync();
    Console.WriteLine(result);
}
else
{
    Console.WriteLine($"Status: {res.StatusCode}");
}

Console.ReadLine();
The server:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;

var builder = WebApplication.CreateBuilder(args);

builder.Services
    .AddAuthentication()
    .AddJwtBearer(cfg =>
    {
        var plainTextSecurityKey = "This is secret";

        var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(plainTextSecurityKey));
        var signingCredentials = new SigningCredentials(signingKey,SecurityAlgorithms.HmacSha256Signature);

        cfg.RequireHttpsMetadata = false;
        cfg.TokenValidationParameters = new TokenValidationParameters()
        {            
            ValidateAudience = false,
            ValidateIssuer   = false,
            IssuerSigningKey = signingKey            
        };

        cfg.Events = new JwtBearerEvents()
        {
            OnAuthenticationFailed = async context =>
            {
                var ex = context.Exception;
                Console.WriteLine(ex.Message);
            }
        };
    });

builder.Services.AddControllers();

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[ApiController]
[Route("api/[controller]")]
public class ExampleController : ControllerBase
{

	public ExampleController()
	{
	}

	[HttpGet]
	public IActionResult Get()
	{
		return this.Ok("webapi service. authenticated as " + this.User.Identity.Name);
	}
}
I love .NET6 way of providing concise examples.

No comments: