Skip to content

JWT and .NET Core Cookie Authentication

Today we are looking into the mysteries of JWT combined with .NET Core! Due to the SPA’s getting
more and more popular it is very likely that you will need to develop one at some point in the future.
Furthermore Microsoft’s latest technology (.NET Core) is a powerfull and modern tool that works really
well with client frameworks such as Angular.

Imagine a scenario where we have an application for an eshop. The store front will be implemented using
an SPA and the backend will be supported by .NET Core. The SPA can communicate via a web secured API
(using JWT!) with the backend. For administration purposes we need to implement a .NET Core application
for helpdesk/back office tasks. Therefore if you have the role ‘Customer’ then you log in from the front end and
get a JWT token, but if you have the role ‘helpdesk’ then you can log in to the administration area
using the default cookie based security.

Visual Studio set up

Let’s get started!
Open up Visual Studio, i currently use the 15.7.6 version.

Go to File -> New -> Project
From left side bar select .NET Core and then ASP .NET Core Web Application.
jwt
In the template selection, be sure to have ASP .NET Core 2.1. If you dont your experience maybe diffrent.
You can download .NET Core 2.1 from Microsoft
jwt
Select the template for WebApplication.
Change Authentication to individual User accounts.

First of all we’ ll go to the appsettings.json file. You can change the default connection to point to an SQL Server database
but for the purposes of this post we’ll use the local db that VS created for us.

Now go to Tools-> NuGet Package Manager-> Package Manager Console
Run the command ‘Update-Database’ to populate the database with the neccessary tables for the authentication
of individual user accounts.

Run the project and you should see something like the image below
jwt
Register a user and keep the username and password because we’ll need them later, and then stop the project.

Main configuration

Go to the StartUp.cs and in the ConfigureServices method put the code


services.AddAuthentication()
.AddCookie(cfg => cfg.SlidingExpiration = true)
.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"]))
 };
});

jwt
As you can see since we want to use both types of authentication in our application we have to chain them,
right after calling the AddAuthentication() method.

Open appsettings.json And put


"Jwt": {
"Key": "SecretKey!",
"Issuer": "http://localhost:44305/"
},

jwt

For the port number i’ve put the port that my app is using when running.
Check that everything is ok by launching the app and logging in with the user you created earlier.

Controllers

Values Controller, for testing

Create a new folder called Controllers and then create two controllers named Token and Values.
right click-> Controller-> API Controller -Empty press add, and then write the name of the controller
jwt

Copy and paste the code below for your Values Controller


[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
 [HttpGet, Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
 public ActionResult<IEnumerable<string>> Get()
 {
  return new string[] { "value1", "value2" };
 }
}

This Get method is now secured and only if we have a valid token can we access it.

Create the JWT responsible Controller

Now let’s start coding the Token Controller that will be responsible for the JWT token creation.

Go to your token controller and create two inner classes that will helps us with our mock login


public class LoginModel
{
 public string Username { get; set; }
 public string Password { get; set; }
}

private class UserModel
{
 public string Name { get; set; }
 public string Email { get; set; }
 public DateTime Birthdate { get; set; }
}

Create a method for our Mock login Called Authenticate


private UserModel Authenticate(LoginModel login)
{
 UserModel user = null;

 //Mock login
 if (login.Username == "code" && login.Password == "excavator")
 {
   user = new UserModel { Name = "Code Excavator", Email = "info@codeexcavator.com"};
 }
 return user;
}

Add another method called BuildToken that is the methoed where the actual JWT Token is created and also add access to the appsettings
by using the IConfiguration.

private IConfiguration _config;

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

private string BuildToken(UserModel user)
{
  var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
  var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

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

   return new JwtSecurityTokenHandler().WriteToken(token);
}

Now we can build our token but there is no way to access it from outside, that’s why we’ll create another method called CreateToken

[AllowAnonymous]
[HttpPost]
public IActionResult CreateToken([FromBody]LoginModel login)
{
 IActionResult response = Unauthorized();
 var user = Authenticate(login);

 if (user != null)
 {
  var tokenString = BuildToken(user);
  response = Ok(new { token = tokenString });
 }

 return response;
}

We now have in our Token Controller a method that will return a valid token if we send the correct username and password
from a post request. Every subsequent request having that token will be able to access our Values Controller.

Final steps

Everything is in place so run the app and test it!

Run the project from Visual Studio. Try to login and logout with the user you created earlier to check that the cookie login works
properly and nothing is broken. Then open a program like Postman and make the call to get the JWT token.
jwt
401 Unauthorized since the username was wrong
jwt

When we have our token returned successfully, then we can try to call the values controller.

jwt
401 Unauthorized since we did nto include a token in our request
jwt
Successfull call with our token.
jwt

Summary

This was a super simple implementation of JWT authentication combined with the default cookie authentication,
instead of using the Identity server or any other complicated code. Of course this not ready for a production
environment but it should give you the much needed head start to begin experimenting with .NET Core and SPA’s.

This post was based on another post at the Auth0 blog by Andrea Chiarelli and you should definelty check it out!.
Other useful links are Shawn Wildermuth’s Blog and mmacneil

Clone or download the source code of this project from Github (Folder net-core-jwt).
Finally you can always Buy me a coffeeBuy me a coffee and help me stay awake to continue my excavations!

2

One Comment

  1. Very helpful and detailed, thanks!

Leave a Reply

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