Click here to Skip to main content
13,900,000 members
Click here to Skip to main content
Add your own
alternative version

Stats

23.2K views
25 bookmarked
Posted 28 Nov 2017
Licenced CPOL

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

, 1 Dec 2017
Rate this:
Please Sign up or sign in to vote.
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Raihan Alam
Software Developer (Senior)
Australia Australia
No Biography provided

You may also be interested in...

Comments and Discussions

 
Questionjwt with external providers Pin
Member 769978624-Oct-18 10:08
memberMember 769978624-Oct-18 10:08 
QuestionAre you really authenticating with JWT Token? Pin
Member 1375195728-Mar-18 9:34
memberMember 1375195728-Mar-18 9:34 
QuestionUses both cookie and token Pin
raju dasa27-Dec-17 20:22
memberraju dasa27-Dec-17 20:22 
AnswerRe: Uses both cookie and token Pin
Raihan Alam2-Jan-18 2:10
professionalRaihan Alam2-Jan-18 2:10 
GeneralRe: Uses both cookie and token Pin
raju dasa8-Jan-18 4:18
memberraju dasa8-Jan-18 4:18 
QuestionNo TokenController in the source code download Pin
George Wallace30-Nov-17 5:54
memberGeorge Wallace30-Nov-17 5:54 
AnswerRe: No TokenController in the source code download Pin
Raihan Alam1-Dec-17 2:30
professionalRaihan Alam1-Dec-17 2:30 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web05 | 2.8.190306.1 | Last Updated 1 Dec 2017
Article Copyright 2017 by Raihan Alam
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid