Secure .NET Core Api Server and Client

 Hi Guys,

Recently I had a requirement to create a JWT token based WebApi server and a WebApi Client to consume it using .NET Core.

So first I created two .NET Core Web Api projects as shown below.











In the appsettings.json file of both the WebApi Server and the Client. I added the following values.


 "JwtConfig": {  

  "Key": "dsadsagfaqrergsdsfdffdsfdsffdsfdsfdsfdsfdfdsfsfdsfd", //Some Secure Key longer the better  

  "AudienceId": 7895, //Some Secure Audience Id  

  "HostUrl": "https://somesecureurl.com" //Some Host Url  

 }  

Now we will first look at implementation of the WebApi Server.

1) First we must create code to Generate the JWT token, this can be achieved by creating JWTTokenManager.cs file and adding following code


 public interface IJwtTokenManager  
 {  
   string Authenticate(string userName, string password);  
 }  
 public class JwtTokenManager : IJwtTokenManager  
 {  
   private readonly IConfiguration _configuration;  
   public JwtTokenManager(IConfiguration configuration)  
   {  
     _configuration = configuration;  
   }  
   public string Authenticate(string userName, string password)  
   {  
     var key = _configuration.GetValue<string>("JwtConfig:Key");  
     var keyBytes = Encoding.ASCII.GetBytes(key);  
     var tokenHandler = new JwtSecurityTokenHandler();  
     var tokenDescriptor = new SecurityTokenDescriptor  
     {  
       Subject = new ClaimsIdentity(new Claim[]  
        {  
        new Claim(ClaimTypes.NameIdentifier, userName)  
        }),  
       Audience = _configuration.GetValue<string>("JwtConfig:AudienceId"),  
       Issuer = _configuration.GetValue<string>("JwtConfig:HostUrl"),  
       Expires = DateTime.UtcNow.AddMinutes(30),  
       SigningCredentials = new SigningCredentials(  
                  new SymmetricSecurityKey(keyBytes),  
                  SecurityAlgorithms.HmacSha256Signature)  
     };  
     var token = tokenHandler.CreateToken(tokenDescriptor);  
     return tokenHandler.WriteToken(token);  
   }  
 }  


2) In the Program.cs file we must add the following code for the JwtTokenManager to be instantiated.

builder.Services.AddScoped<IJwtTokenManager, JwtTokenManager>();

3) Now we will create a Controller the Client to call and obtain the JWT token and add the following code.


  [ApiController]  
  [Route("[controller]")]  
  public class AuthController : ControllerBase  
  {  
    private readonly ILogger<AuthController> _logger;  
    private readonly IJwtTokenManager _jwtTokenManager;  
    public AuthController(ILogger<AuthController> logger,  
      IJwtTokenManager jwtTokenManager)  
    {  
      _logger = logger;  
      _jwtTokenManager = jwtTokenManager;  
    }  
    [AllowAnonymous]  
    [HttpPost("token")]  
    public IActionResult Login([FromBody] UserCredential user)  
    {  
      //Check credentials against your user repository  
      if (true)  
      {  
        var token = _jwtTokenManager.Authenticate(user.Username, user.Password);  
        return Ok(token);  
      }  
      return Unauthorized();  
    }  
  }  

4) Now we can generate the JWT token as shown below.




Now since we have the JWT Token generated we will now look at the implementation of Client WebApi

1) First in the Program.cs we must add the below code to let the Client know that it will authenticating requests using JWT Tokens


 string audienceId = builder.Configuration.GetValue<string>("JwtConfig:AudienceId");  
 string symmetricKeyAsBase64 = builder.Configuration.GetValue<string>("JwtConfig:Key");  
 var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);  
 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)  
        .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>  
        {  
          options.TokenValidationParameters = new TokenValidationParameters  
          {            
            ValidIssuer = builder.Configuration.GetValue<string>("JwtConfig:HostUrl"),             
            ValidateIssuer = true,  
            ValidateAudience = true,  
            ValidateLifetime = true,  
            ValidateIssuerSigningKey = true,             
            ValidAudience = audienceId,  
            IssuerSigningKey = new SymmetricSecurityKey(keyByteArray)  
          };  
        });  

2) Then inside our WeatherForecast controller we will add the Authorize attribute to let the Client know that all requests to this controller must have a valid bearer token




3) Now we can call the Client with the JWT Token we obtained from the WebApi Server as shown below








Comments

Popular posts from this blog

WCF Service and TLS 1.2

Calling ChatGPT using .NET Core