Simple Authentication and Authorisation in ASP.NET Core Web API

Teng Wei Song
4 min readOct 27, 2018

--

Web API often needs to be protected from malicious users. This article aims to show how simple authentication and authorisation can be implemented in a sample ASP.NET Core Web API app (“sample app”).

Photo by rawpixel on Unsplash

I have used the following tools to build the sample app:

  • Visual Studio Code (my favourite code editor)
  • SQL Server (it was run inside a Docker container because the sample app was built in macOS)
  • EntityFramework Core (a good ORM that came with ASP.NET Core)

How the Simple Authentication and Authorisation Works

With authentication and authorisation implemented, my sample ASP.NET Core Web API app only accepts HTTP request with valid JSON web token (JWT). A database table is used to store the list of approved users.

Below is a brief illustration of how the sample app works:

  1. A client app sends an HTTP request to the sample app which resides in a server to authenticate the user.
  2. The sample app uses the data received to check if there is a matching entry in the database. If there is a matching user in the database, the app will send a message with an OK result and a JSON web token (JWT) back to the client app. The JWT also includes various claims which can be used to determine the user permission to certain endpoints.
  3. After receiving the JWT, the client app will include this token in the header of each subsequent HTTP request to the sample app.

Steps to Implement Authentication

Doesn’t it look easy? It is indeed not difficult to implement the above-mentioned mechanism in a Web API app. The steps I have taken to create this sample app is shown below.

Step 1: Add User table in database

First, we need a database to store the information of permitted users. Here I used EntityFramework Core to add a table called User in my SQL Server database with a couple of simple steps:

  1. Create a domain class User with some properties such as UserName , Password, and Token.
  2. Use the bash commands dotnet ef migrations add [migration name]and dotnet ef database updateto create the table in the database. After the database is created using the migrations, I then seeded the Users table with some entries.

Step 2: Get Secret key and prepare authentication at StartUp class

A secret key is used to encrypt the JWT. It can be stored inside our appsettings.json file. We need to retrieve this value in our application. To achieve this, I made use of the Configuration class. First I created a IdentitySettings domain model with a single propertySecret:

public class IdentitySettings
{
public string Secret { get; set; }
}

which would be used to map the Secret from the appsettings.json file.

"IdentitySettings":{
"Secret":"THIS IS A SECRET KEY"
},

I also needed to instantiate this object in StartUp class along with codes necessary for authentication:

Lastly, I enabled authentication in the Configure method:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
app.UseAuthentication();
...
}

Step 3: Implementing AuthService

I created a new interface IAuthService and implement it with AuthService:

This AuthService class contains a method called Authenticate which would be used to verify the incoming user detail against the database before generating a token string which would eventually sent back to the sender (the client app).

Step 4: Listen to authentication request in UsersController

Since this sample app follows an MVC architecture pattern, a controller was used to ensure the request was received and directed to appropriate services. In my case, a UserController was used to listen to this request and AuthService was used to get the job done.

[Authorize]
[Route("/api/users")]
public class UsersController : Controller
{
...
[AllowAnonymous]
[HttpPost("auth")]
public IActionResult Authenticate([FromBody] User user)
{
var validUser = authService.Authenticate(user.UserName);
if(validUser == null)
return BadRequest();
return Ok(validUser);
}
}

Step 5: Authorisation and claims

To this stage, the authentication is considered done. Controller or endpoints can now be protected from invalid or unregconised users. Optionally, we could make this app better by adding the customised authorisation. For example, only user with role as admin could work with the DocumentsController. In my sample app, I used claim-based authorisation for HTTP requests:

[Authorize("IsAdmin")]
[Route("api/documents")]
public class DocumentsController : Controller
{
...
}

which required authorisation options to be declared in StartUp class:

public void ConfigureServices(IServiceCollection services)
{
services.AddAuthorization(options =>
{
options.AddPolicy("IsAdmin", policy =>
{
policy.RequireClaim(ClaimTypes.Role, "admin");
});
});
}

and this claim was read from database and written to the token in AuthService class Authenticate method:

var tokenDescriptor = new SecurityTokenDescriptor
{
...
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.Role, user.Role)
}
...
}

This sample Web API app shows how authentication and authorisation can be easily implemented without using any third-party library. Certainly, this sample only verified user with just the UserName. In real world application, password must be used for identity verification.

--

--

Teng Wei Song

My journey as a self-taught developer. Feel free to drop by my online profile at tengweisong.com as well!