React ASP.NET Core SignalR Chat | JWT Login (Part 2)

This is the second part of the React js and Signalr chat application. Check out the previous article so you can follow up.

Lets begin!

In this part we setup ASP.NET Core server with MVC. We’ll create JWT based login 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 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.

To be continued, will update this article shortly.

1 Reply to “React ASP.NET Core SignalR Chat | JWT Login (Part 2)”

Leave a Reply

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