Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

ASP.NET Core Identity: Supporting JWT Token for User Authentication

0.00/5 (No votes)
1 Dec 2017 1  
JWT token support in ASP.NET Core Identity

Introduction

This is the third article of a series of articles on ASP.NET Core Identity:

In the previous steps, we created an ASP.NET Core MVC web site with Login/Logout functionalities using ASP.NET Core Identity. The MVC web site that we built used cookie based authentication which works fine for that scenario. But for many other scenarios (like consuming a secure API from a mobile app), cookie based approach is not a good option. One popular approach for those scenarios is token based authentication. In this step, we are going to add jwt token generation capability for authentication to our project.

I am not going to explain the details of what is a JWT token and how it is different from cookie based approach as there are tons of really good articles on this topic. If you are interested, you can have a look at these articles:

  1. https://auth0.com/blog/angularjs-authentication-with-cookies-vs-token/
  2. https://auth0.com/blog/ten-things-you-should-know-about-tokens-and-cookies/
  3. https://medium.com/vandium-software/5-easy-steps-to-understanding-json-web-tokens-jwt-1164c0adfcec

The complete code for this article is available in the Demo 3 folder in this repo https://github.com/ra1han/aspnet-core-identity.

Preparing the Services in Startup

To enable JWT token generation, we have to configure the services for identity middleware. But if we look at the current implementation of ConfigureServices method in Startup class, we will see that there is no configuration for cookies.

Then how is the cookie based authentication working? That's working because if we don't manually configure it, the default behaviour is Cookie based authentication.

We will use services.AddAuthentication in ConfigureServices method to add additional authentication scheme.

public void ConfigureServices(IServiceCollection services)
{
	services.AddDbContext<applicationdbcontext>(options =>
					options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

	services.AddIdentity<applicationuser, identityrole="">()
											.AddEntityFrameworkStores<applicationdbcontext>()
											.AddDefaultTokenProviders();

	services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
			.AddCookie()
			.AddJwtBearer(jwtBearerOptions =>
			{
				jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters()
				{
					ValidateActor = false,
					ValidateAudience = false,
					ValidateLifetime = true,
					ValidateIssuerSigningKey = true,
					ValidIssuer = Configuration["Token:Issuer"],
					ValidAudience = Configuration["Token:Audience"],
					IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes
                                                       (Configuration["Token:Key"]))
				};
			});

	services.AddMvc();
}

Preparing the Controllers

Now, we will add two new web API controllers:

  • TokenController - Anonymously accessible, this is used by the user to retrieve the JWT token
  • GreetingController - Secured and only accessible using JWT Token authentication scheme

The token generation code in TokenController:

[HttpPost]
public async Task<iactionresult> Get(LoginViewModel model)
{
	if (ModelState.IsValid)
	{
		var user = await _userManager.FindByEmailAsync(model.Email);
		if (user != null)
		{

			var result = await _signInManager.CheckPasswordSignInAsync
                            (user, model.Password, lockoutOnFailure: false);

			if (!result.Succeeded)
			{
				return Unauthorized();
			}

			var claims = new[]
			{
				new Claim(JwtRegisteredClaimNames.Sub, model.Email),
				new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
			};

			var token = new JwtSecurityToken
			(
				issuer: _configuration["Token:Issuer"],
				audience: _configuration["Token:Audience"],
				claims: claims,
				expires: DateTime.UtcNow.AddDays(60),
				notBefore: DateTime.UtcNow,
				signingCredentials: new SigningCredentials(new SymmetricSecurityKey
                            (Encoding.UTF8.GetBytes(_configuration["Token:Key"])),
						SecurityAlgorithms.HmacSha256)
			);

			return Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token) });
		}
	}

	return BadRequest();
}

Using the API

Now to test our implementation, we shall use Postman.

First, we shall try to access Greeting API (http://localhost:36946/api/greeting) from postman. We will see that we get Unauthorized error.

Now let's create a token from Token API (http://localhost:36946/api/token). We will provide the username and password and the API will return the bearer token.

Now let's call the Greeting API again with the bearer token.

It worked! In the next article, we shall create an Angular 4 project with user authentication functionalities developed in this step.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here