If you have a web API application, you might want to authenticate your user before letting them access your APIs. While I was working with mine, I found two approaches that I could follow -

Let’s get into details.

JSON web Token:

JSON web token has three parts separated by dots. These are:

  1. The header: contains some metadata about the token itself.
  2. The payload: contains the data that we want to encode into the token, so the more data we want to encode here the bigger is the JWT.
  3. The signature.

The first two parts are not encrypted. They are just encoded. Anyone will be able to decode, read and even change them. So to maintain it’s security, the third part, signature, is used.

Signature is generated using the header, the payload and a secret kept by the server. The process is called signing the JSON web token. At the time of validating the token, server generates the signature again with the header and payload present in the token along with the secret. It then compares the newly generated signature with the signature present in the token. If someone changes the header and payload, the signatures won’t match and the caller won’t be given access.

Here’s how to implement JWT authentication for an ASP.NET web API app.

First we need an API, maybe called “Login”, for the client to collect the JWT from the server. This API will take the user’s email and return a JWT token.

var tokenHandler = new JwtSecurityTokenHandler();
var tokenKey = Encoding.UTF8.GetBytes(_iconfiguration["JWT:Key"] ?? "");
var tokenDescriptor = new SecurityTokenDescriptor
{
    Subject = new ClaimsIdentity(
        new Claim[] { new Claim(ClaimTypes.Email, userEmail) } //userEmail is provided by the client
    ),
    Expires = DateTime.UtcNow.AddMinutes(10),
    SigningCredentials = new SigningCredentials(
        new SymmetricSecurityKey(tokenKey),
        SecurityAlgorithms.HmacSha256Signature
    )
};
var jwToken = tokenHandler.CreateToken(tokenDescriptor);
return new OkObjectResult(
    new TokenDto { Token = tokenHandler.WriteToken(jwToken) }
);

Then in Program.cs add the following, so that our app always expects a token:

builder.Services.AddAuthentication(x =>
{
    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
    var Key = Encoding.UTF8.GetBytes(builder.Configuration["JWT:Key"] ?? "");
    o.SaveToken = true;
    o.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = false,
        ValidateAudience = false,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = builder.Configuration["JWT:Issuer"],
        ValidAudience = builder.Configuration["JWT:Audience"],
        IssuerSigningKey = new SymmetricSecurityKey(Key)
    };
    o.Events = new JwtBearerEvents()
    {
        OnMessageReceived = ctx => {
            if (ctx.Request.Headers.TryGetValue("Authorization", out var headerValue)) {
                var splittedValues = headerValue.ToString().Split(" ");
                if (splittedValues.Length >= 2 && splittedValues[0] == "Bearer") {
                    ctx.Token = splittedValues[1];
                }
            }
            return Task.CompletedTask;
        }
    };
});

Usually, this token is sent to the server as a “bearer” token in the header of a request. For that purpose, a client can follow various approaches to save this token locally such as using cookies, local storage, local variables etc. But not every approach is safe. Most of these approaches easily become vulnerable to either XSS(Cross Site Scripting) or CSRF(Cross Site Request Forgery) attack. XSS is an attack where an attacker injects some javascript code into the client side application. When that code runs on the client browser, the attacker can steal some valuable information from that client. If enough measure is not taken while storing the JWT token on client side, this can be easily stolen by XSS attack.

Again, CSRF is an attack that forces an end user to execute unwanted actions on a web application in which they’re currently authenticated. Mostly cookies are exploited in this attack.