JWT Token based Authentication in ASP Net Core Web API

 11-Oct-2017   nityaprakash     ASPNETCORE  BEARER  TOKEN    Comments  2

In this post, I am going to show how can we implement JWT Token base authentication in ASP.NET Core 2.0 Web API (REST API). There are slight change in ASP.NET Core 2.0 in creating JWT token from ASP.NET Core 2. I haven't work on ASP.NET Core 1.x in much so I can't deep dive in this.

Why Token base Authentication

In regular ASP.NET application or Web API, Authentication handled via cookie. SessionID set in cookie after authentication on server and stored on client. It can be transient cookie which will expire as soon as you close the browser or logout from the session, or persistent cookie on the client. Cookie base authentication is stageful communication server and browser automatically passed the cookie to the for authentication. However, JWT token based authentication is stateless and server doesn't keep the record who logged in. It returns the token as JSON response to the client and it's client's responsibility to store locally and pass in Authorization header. Followings are the advantage of Token-Based Authentication:

  • Stateless, Scalable and Decoupled.
  • Cross Domain and CORS
  • Store Data in the JWT
  • Performance
  • Mobile Ready

There is very good explanation about Token-based authtenticatoin here. My goal here is to implement on ASP.NET Core 2.0 Web API.

Configuring JWT Token

As we aware that, all configuration or ASP.NET Core applications happen in Startup class in Startup.cs file. There are two methods ConfigureServices and Configure. Write below code in ConfigureService method.


 services.AddAuthorization(options=>{
                options.DefaultPolicy = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme)
                    .RequireAuthenticatedUser()
                    .Build();
            });

            services.AddAuthentication(o=>{
                o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(options =>{
                options.TokenValidationParameters = new TokenValidationParameters{
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = "Your Website address",
                    ValidAudience = "Your Website address",
                    IssuerSigningKey = new SymmetricSecurityKey( Encoding.ASCII.GetBytes("lengthy secrete key"))

                };
            });

Add app.UseAuthentication() statement in Configure method before app.UseMvc() method.


 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseStaticFiles();

            app.UseAuthentication();

            app.UseMvc();

        }

This is what we need for configuration only.

Creating Token Controller

This will be API which client will call to get token. Token is self contains information about the authenticated user. It can contains name, email roles and other claims including expiration. This will be generated with the same secrete key, Issuer and Audience that were used to configure the authentication in above code. Here how the TokenController will look like.


[AllowAnonymous]
    [Route("api/[controller]")]
    public class TokenController : Controller
    {
		private readonly UserManager userManager;
		private readonly SignInManager signInManager;

        public TokenController(UserManager userManager, SignInManager signInManager)
        {
            this.userManager = userManager;
            this.signInManager = signInManager;
        }

        // GET: api/values
        [HttpGet]
        public async Task Get(string username, string password, string grant_type)
        {
			
                var user = await userManager.FindByEmailAsync(username);

                if (user != null)
		{
                    var result =await signInManager.CheckPasswordSignInAsync(user, password, false);
                    if (result.Succeeded)
		    {

				var claims = new[]
				{
                                        new Claim(JwtRegisteredClaimNames.Sub, username),
					new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
					new Claim( JwtRegisteredClaimNames.GivenName, "Nitya Prakash Sharma")
				};

			       var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("lengthy secrete key"));
				var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

                              var token = new JwtSecurityToken( issuer: "Your Website address",
                                                                                           audience: "Your Website address",
                                                                                            claims: claims,
                                						  	   expires: DateTime.Now.AddDays(15),
                                						  	 signingCredentials: creds);

                            return Ok(new { access_token = new JwtSecurityTokenHandler().WriteToken(token), expires_on=DateTime.Now.AddDays(15) });
				}
			}
			

			return BadRequest("Could not create token");
        }


    }

JWT Token-Based Authentication is ready to use. Your secrete key should be more than 8 character. Claims used to generate token can have any information we want to have it in token. This token is signed with HMACSHA256 algorithms but it is not encrypted.

Testing with POSTMAN

Run the WebAPI with dotnet run cli command.


Using launch settings from /Users/user/Projects/DemoSolution/DemoAPI/Properties/launchSettings.json...
Hosting environment: Development
Content root path: /Users/user/Projects/DemoSolution/DemoAPI
Now listening on: http://localhost:5000

Application started. Press Ctrl+C to shut down.

We can test Token API using Google Postman. Please see screenshot below. The way we designed our API is that we are passing the user id and password as query parameter with Content-Type as application/x-www-form-urlencoded.

We can use this access_token in subsequent requests for authentication as Authorization Header.

Wrapping Up

This post explains how we can make WebAPI in ASP.NET Core 2.0 to use Token-Based Authentication. That way our API can be used in Single Page Application using Angular and Mobile application using Android and IOS.


Nitya Prakash Sharma has over 10 years of experience in .NET technology. He is currently working as Senior Consultant in industry. He is always keen to learn new things in Technology and eager to apply wherever is possible. He is also has interest in Photography, sketching and painting.

My Blog
Post Comment

COMMENTS


Gregory Goraj
24-Nov-2017

Outdated?

Hi, I've noticed that I can not configure JWTBearerDefaults in Startup.cs the way You propose. I think its actualy simplyfied in dotnet core 2.0 - its method from 1.0 according to this: https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x


Gregory Goraj
24-Nov-2017

Nop, sory, I was wrong

;) I simply dont understand how to declare JwtBearerDefaults since the code doesn't work... VSCode points out: JwtBearerDefaults doesn't exist in current context... Could You help me please?