Token based authentication in ASP.NET Core

October 06, 2017 by Anuraj

ASP.NET Core Authentication JWT

This post is about token based authentication in ASP.NET Core. The general concept behind a token-based authentication system is simple. Allow users to enter their username and password in order to obtain a token which allows them to fetch a specific resource - without using their username and password. Once their token has been obtained, the user can offer the token - which offers access to a specific resource for a time period - to the remote site.

To use Token or JWT authentication, first you need to configure JWT Authentication middleware.

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(jwtBearerOptions =>
    {
        jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters()
        {
            ValidateActor = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = Configuration["Issuer"],
            ValidAudience = Configuration["Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["SigningKey"]))
        };
    });

    services.AddMvc();
}

You’re done the configuration, now need to add the authentication middleware to application builder. You can do it in the Configure method.

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

    app.UseAuthentication();
    app.UseMvc();
}

Now you need a controller action method, which helps users to generate token.

[AllowAnonymous]
[HttpPost]
[Route("token")]
public IActionResult Post([FromBody]LoginViewModel loginViewModel)
{
    if (ModelState.IsValid)
    {
        //This method returns user id from username and password.
        var userId = GetUserIdFromCredentials(loginViewModel); 
        if (userId == -1)
        {
            return Unauthorized();
        }

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

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

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

    return BadRequest();
}

Now you can protect the resources using [Authorize] attribute.

[Authorize]
[Route("api/[controller]")]
public class ValuesController : Controller
{
    [HttpGet]
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }
}

Here is the screenshot of POSTMAN get request without header.

ASP.NET Web API Request without header

Now you can generate the token using Token endpoint with the username and password, which will generate the token.

Generating token with token endpoint

Next, you can request the values controller with Authorization header with the token received from Token endpoint, which will return the values.

ASP.NET Web API Request with header

If you’re using JQuery, you can use JQuery Ajax method with header like this.

$.ajax({
    type: 'GET',
    url: '/api/values',
    headers: {
        "Authorization": "Bearer YOUR-TOKEN"
    }
}).done(function (data) {
    console.log(data);
});

Source code available on GitHub

Happy Programming :)

Copyright © 2024 Anuraj. Blog content licensed under the Creative Commons CC BY 2.5 | Unless otherwise stated or granted, code samples licensed under the MIT license. This is a personal blog. The opinions expressed here represent my own and not those of my employer. Powered by Jekyll. Hosted with ❤ by GitHub