Chat app using React.js + ASP.NET SignalR Core | JWT Login (Part 2)

This is the second part of our ASP.NET Signalr Core + React chat application series. If you want to read first part, check it out here: React js and Signalr chat application.

In previous article we setup our React js application. We created the chat UI (Login and chat room screens). We will create a simple jwt based authentication system in this part.

ASP.NET Core Signalr JWT Authentication

In this part we setup ASP.NET Core server with MVC. We’ll use the JWT authentication system (no database for now) and let our users login to our chat app.

Create a new ASP.NET Core Web App Project.

We need to add MVC to the project, you can select from project creation winow or you can also add it through Services. Also we need to allow our React app through the CORS policy.

Open your Startup.cs file and add the folloing lines to ConfigureServices method and in Configure method:

// Add this to ConfigureServices method
services.AddCors();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
// Add this to Configure method
app.UseCors(builder => builder
            .AllowAnyOrigin() // allow all origins
            .AllowAnyMethod() // allow all methods
            .AllowAnyHeader() // allow any header
            .AllowCredentials()); // allow credentials

app.UseMvc();

You can read more about CORS policies here. You can allow only react development app on a specific port. Its up to you. You can disable CORS policy after you’ve uploaded app on the server if its on the same server.

Now your basic ASP.NET Core server app is done. Now we are going to add JWT authentication to it.

What is JWT authentication and Why should I use it?

JWT or JSON Web Token is one of the most simplest way of token based authentication which you can easily implement in under 15 minutes. It allows you to have a payload as well which you can use on the front end to pass values like Role, UserId, etc. You can read more about JWT Authentication here

To enable JWT authorization in ASP.NET Core API, do the following steps:

// Add this to ConfigureServices method in Startup.cs

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = Configuration["Jwt:Issuer"],
        ValidAudience = Configuration["Jwt:Issuer"],
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
    };
});

Also add a constructor with IConfiguration dependency injection like this:

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}

public IConfiguration Configuration { get; }

Create an appsettings.json file in the root of your project if you don’t have, to store Key and Issuer values which are required to make it work. In appsettings.json you should have:

"Jwt": {
  "Key": "ThisismySecretKey", // never tell this secret key to any user
  "Issuer": "www.techcuriosity.net" // issuer of this token
}

Now the JWT authentication service is configured. Let’s create a LoginController and add methods in it to Generate JWT Token using claims (user properties) and a method to Authenticate user which in this case will simply check if user is Waleed or Superman.

// Inject dependency in LoginController through constructor

private IConfiguration _config;

public LoginController(IConfiguration config)
{
    _config = config;
}	

Add a Login method which takes Username and Password as input and bind it to AuthenticationModel in our Models folder

[AllowAnonymous]
[HttpPost]
public IActionResult Login([FromForm] AuthenticationModel model)
{

    try
    {

        var token = AuthenticateUser(model);

        var tokenString = GenerateJSONWebToken(token);

        return Ok(new { token = tokenString });

    }
    catch (Exception e)
    {
        return StatusCode(500, e.Message);
    }

}

We are going to use this View model for binding Username and Passwords from the form. This is called Model binding.

public class AuthenticationModel
{

    [Required]
    public string Username { get; set; }

    [Required]
    public string Password { get; set; }
    
}

Add AuthenticateUser method which is used by above Login method for authenticating users.

private AuthenticationModel AuthenticateUser(AuthenticationModel model)
{

    if (ModelState.IsValid)
    {

        // we are simply checking if username is waleed or superman, you can implement your database logic here if you want.
        if(model.Username == "Waleed" || model.Username == "Superman")
        {
            return model;
        }

    }

    return model;

}

GenerateJSONWebToken This is the core method, this generates the JWT Token. In this method we are using the key to sign it. We are also adding the Username claim into the JWT token.

private string GenerateJSONWebToken(AuthenticationModel model)
{

    var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
    var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

    var claims = new[] {
            new Claim("Username", model.Username),
        };

    var token = new JwtSecurityToken(_config["Jwt:Issuer"],
      _config["Jwt:Issuer"],
      claims,
      expires: DateTime.Now.AddMinutes(120),
      signingCredentials: credentials);

    return new JwtSecurityTokenHandler().WriteToken(token);

}

Now JWT part on the server side is done, now we implement the JWT authentication in React front end. Note for the front end part we will use the @aspnet/signalr react package from npm which supports ASP.NET core backend.

To be continued, will update this article shortly.

Leave a Reply

Your email address will not be published. Required fields are marked *