Web API Token Based Authentication

Introduction

In this article, we will learn how to implement Token Based Authentication in Web APIs to secure the data.

There are 4 common methods of Web API Authentication

  1. HTTP Authentication Schemes (Basic & Bearer)
  2. API Keys
  3. OAuth (2.0)
  4. OpenID Connect

Here we will learn OAuth authentication. OAuth is an open standard for token based authentication and authorization on internet. By using OAuth we can create Token Based Authentication API.

What is Token Based Authentication in Web API?

Token-based authentication is a process where the client application first sends a request to Authentication server with a valid credentials. The Authentication server sends an Access token to the client as a response. This token contains enough data to identify a particular user and it has an expiry time. The client application then uses the token to access the restricted resources in the next requests until the token is valid. If the Access token is expired, then the client application can request for a new access token by using Refresh token.

Flowchart

Advantages of Token Based Authentication

  • Scalability of Servers
  • Loosely Coupling
  • Mobile-Friendly

Let’s discuss the step by step procedure to create Token-Based Authentication.

Step 1. Create ASP.NET Web Project in Visual Studio 2019.

We have to create web project in Visual Studio as given in the below image. Choose ASP.Net Web Application from the menu.

Create New Project

Give the project name as WEBAPITOKENAUTHENTICATION.

Configure

Now choose the empty template and check the "MVC" and "Web API" on the right hand side.

Create New Web App

Step 2. Addition Of References

In this step,we have to add Nuget References like the below image.

NuGet Reference

Here we have to add the following references.

  • Microsoft.Owin.Host.SystemWeb
  • Microsoft.Owin.Security.OAuth
  • Microsoft.Owin.Cors

Add Reference

Security Addon

Cors Addon

Step 3. Create APIAUTHORIZATIONSERVERPROVIDER.cs Class File

Now, let's create the class file to provide credentials to access data depending on username, password, and roles.

API Auth

Code is given below

public class ApiAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
    public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        context.Validated();
    }

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        var identity = new ClaimsIdentity(context.Options.AuthenticationType);

        if (context.UserName == "admin" && context.Password == "admin")
        {
            identity.AddClaim(new Claim(ClaimTypes.Role, "admin"));
            identity.AddClaim(new Claim("username", "admin"));
            identity.AddClaim(new Claim(ClaimTypes.Name, "Hi Admin"));
            context.Validated(identity);
        }
        else if (context.UserName == "user" && context.Password == "user")
        {
            identity.AddClaim(new Claim(ClaimTypes.Role, "user"));
            identity.AddClaim(new Claim("username", "user"));
            identity.AddClaim(new Claim(ClaimTypes.Name, "Hi User"));
            context.Validated(identity);
        }
        else
        {
            context.SetError("invalid_grant", "Provided username and password are incorrect");
            return;
        }
    }
}

Step 4. Create a AuthenticationStartup.cs Class File

Here, we need to create a new class file to implement the code configuration provider and create an instance of class APIAUTHORIZATIONSERVERPROVIDER.

Auth Startup

Code is given below.

public class AuthenticationStartup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

        var myProvider = new ApiAuthorizationServerProvider();

        var options = new OAuthAuthorizationServerOptions
        {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
            Provider = myProvider
        };

        app.UseOAuthAuthorizationServer(options);
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

        var config = new HttpConfiguration();
        WebApiConfig.Register(config);
    }
}

Step 5. Create a APIAUTHORIZEATTRIBUTE.cs Class File.

We need to create this class to handle unauthorized access to resources and show the proper message.

Auth Atrribute

Code is given below.

public class ApiAuthorizeAttribute : System.Web.Http.AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        if (!HttpContext.Current.User.Identity.IsAuthenticated)
        {
            base.HandleUnauthorizedRequest(actionContext);
        }
        else
        {
            actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Forbidden);
        }
    }
}

Step 6. Create a controller with name UserController

Now we have to create an empty web api controller with name usercontroller. In this controller, we will write the actions with different authorization and roles.

Create Controller

The first action "Get" will be available for anonymous users .No authetication or token is needed for this.

[AllowAnonymous]
[HttpGet]
[Route("api/data/forall")]
public IHttpActionResult Get()
{
    return Ok("Now server time is: " + DateTime.Now.ToString());
}

The second action "GetForAuthenticate" only allows the authorized user to access it.

[Authorize]
[HttpGet]
[Route("api/data/authenticate")]
public IHttpActionResult GetForAuthenticate()
{
    var identity = (ClaimsIdentity)User.Identity;
    return Ok("Hello " + identity.Name);
}

The third action "GetForAdmin" checks authorization and allows only admins to access it.

[Authorize(Roles = "admin")]
[HttpGet]
[Route("api/data/authorize")]
public IHttpActionResult GetForAdmin()
{
    var identity = (ClaimsIdentity)User.Identity;
    var roles = identity.Claims
        .Where(c => c.Type == ClaimTypes.Role)
        .Select(c => c.Value);

    return Ok("Hello " + identity.Name + " Role: " + string.Join(",", roles.ToList()));
}

Step 7. Accessing the controller using Postman

Now we have to access the controller. For that purpose, we are using postman to get data.I n case ofthe first action "Get",we can access the data without generating a token as no authorization is needed for it, by just sending GET request for route "api/data/forall".

Access Controller

But for the rest of the actions, we have to generate a token using credentials. So we have to do post request for the token.

Generate Token

Now once the token is generated for the "user" now we can easily access the actions by using the user token.

Postman Testing

Similarly, we can access the action as "admin" by generating token as admin and then using it.

FInal TEst

In the same way, the other actions can be accessed by user or admin depending on the way the token is generated.


Similar Articles