In this article, we will learn how to implement Token Based Authentication in Web API
to secure the server resources using OAuth.
Introduction
In this article, we will learn how to implement Token Based Authentication in Web API
to secure the server resources.
There are 3 Common Methods of Web API Authentication:
- HTTP Basic Authentication
- API Keys
- OAuth
Here I am using OAuth authentication. OAuth is not
technically an authentication method, but a method of both authentication and
authorization. By using OAuth we can create Token Based Authentication API. First,
what is Token Based Authentication in
Web API, advantages of Token Based Authentication in Web API and how does it work?
What is Token Based Authentication in Web API?
Token-based authentication is a process where
the user sends his credential to the server; server will validate the user
details and generate a token which is sent as response to the users with
each and every request. This token is then used to access protected
pages or resources instead of the login credentials for a designated period of
time. This is called the Token Based Authentication approach.
Advantages of Token Based Authentication
- Scalability
of Servers
- Loosely
Coupling
- Mobile
Friendly
How Does Token Based Authentication work?
When a user
enters the name and password into the browser or mobile devices it sends these
credentials (username and password) to the Authorization Server. Then the
Authorization Server authenticates the username and password and then it
generates an access token and returns it as a response to the user. This Access
Token contains the identity of a user and also contains the token expiry time. Then
the client application includes the Access Token in the Authorization header of
the HTTP request to access the restricted resources from the Server until the
token is expired.
Creating the Application.
Here I am using Visual Studio 2019 and .NetFrameWork 4.7 and
Sql Server 2012 to create the example.
Step 1: Creating the
Database.
First, we
create a table to store user info.
Open SQL
Server to create a database with any suitable name and then, create the table.
Here, I am
using "OauthApi" as the database name and "ApiUsers" as the table name.
Tables Structure
- CREATE DATABASE OauthApi
- GO
- USE [OauthApi]
-
- CREATE TABLE [dbo].[ApiUsers](
- [UserId] [int] IDENTITY(1,1) NOT NULL,
- [UserName] [nvarchar](20) NULL,
- [UserPasswd] [nvarchar](50) NULL,
- [UserRole] [nvarchar](50) NULL,
- CONSTRAINT [PK_ApiUsers] PRIMARY KEY CLUSTERED
- (
- [UserId] ASC
- )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
- ) ON [PRIMARY]
- GO
-
- INSERT INTO ApiUsers VALUES(1, 'Amit', '123456', 'SuperAdmin')
- INSERT INTO ApiUsers VALUES(2, 'Subash', 'abc123', 'User')
- INSERT INTO ApiUsers VALUES(3, 'Alok', '123abc123', 'Admin')
- GO
Step 2.1: Creating
the Project
Open Visual Studio, and click on "Create a new
project".
Select ASP.NET web application from templates and click on
"Next".
Then, give the project name as "OauthApp" and then click
"Create".
Now, choose Web API from the template and click on "Create".
Now the application is created.
Step 2.2: Add
references from NuGet packages to the application
After creating the application we have to add the following
references from NuGet packages to the application.
- Microsoft.Owin.Host.SystemWeb
- Microsoft.Owin.Security.OAuth
- Microsoft.Owin.Cors
- Microsoft.AspNet.Identity.Owin
Step 2.3: Creating
the ADO.NET Entity Data Model
To add ADO.NET Entity Data Model right click on the "Models" folder then goto "Add" then click on "New Item" and it will show "Add New
Item" dialog box. From left pannel choose "Data" and then from right pannel
choose "ADO.NET Entity Data Model", named as "DataContext" and click on "Add".
It will open "Entity Data Model Wizard" dialog box. Choose
"EF Designer from database" and click on "Next".
It will open data connection wizard dialog box. Here, create
a new data connection string for data access from the database to the
application. Next click on "New Connection".
It will open connection properties dialog box. Here, we can
see ASO.NET data model provides two types of connection and we can use it as
per our requirement. Here, I am using "SQL Server Authentication" connection
properties and selecting database name and test connection. If it succeeds then press the "OK" button.
Now, we can see the created connection string in the below
image. Here, check the checkbox for the created connection string and save into
the application's web.config file. Then, press Next.
It will open one more dialog box for Database Object and
Setting. Here we can see the created database object list. Here, we can select
the data table from all available tables and giving the Model Namespace as
"DataContextModel" and click on Finish.
Now, you can see created "DataContext.edmx" in "Models"
folder. In this created model, you can see the Model class and diagram as shown
in below image.
Step 2.4: Add
"Startup" Class and add support for OAuth Bearer Tokens Generation
Right click on your project then add new class named
"Startup". To do so, go to the Solution Explorer > Right Click on Project
Name form the Solution Explorer > Add > New Item > Select class >
Enter the class name as Startup.cs > and then click on the Add button and it
will contain the code below:
- using Microsoft.Owin;
- using Microsoft.Owin.Cors;
- using Microsoft.Owin.Security.OAuth;
- using OauthApi.Provider;
- using Owin;
- using System;
- using System.Web.Http;
-
- namespace OauthApi
- {
- public class Startup
- {
- public void Configuration(IAppBuilder app)
- {
- ConfigureAuth(app);
- GlobalConfiguration.Configure(WebApiConfig.Register);
- }
-
- public void ConfigureAuth(IAppBuilder app)
- {
-
-
- app.UseCors(CorsOptions.AllowAll);
-
- var OAuthOptions = new OAuthAuthorizationServerOptions
- {
- AllowInsecureHttp = true,
- TokenEndpointPath = new PathString("/token"),
- AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
- Provider = new OauthProvider()
- };
-
- app.UseOAuthBearerTokens(OAuthOptions);
- app.UseOAuthAuthorizationServer(OAuthOptions);
- app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
-
- HttpConfiguration config = new HttpConfiguration();
- WebApiConfig.Register(config);
- }
- }
- }
Here we created a new instance of the
"OAuthAuthorizationServerOptions" class and then set the path for generating
the tokens will be as "http://localhost:port/token". We have specified the
expiry time for the access token as 30 minutes. We have also specified the
implementation on how to validate the client credentials for users asking for
the access tokens in the custom class named "OauthProvider". Then we passed the
options to the extension method "UseOAuthAuthorizationServer" which will add
the authentication middleware to the pipeline.
No need to use Global.asax
class and fire up the Application_Start event after we’ve configured our
"Startup" class so feel free to delete it.
Step 2.5: Implement
the "OauthProvider" class
Add new folder named "Providers" to the project then add new
class named "OauthProvider", paste the below code snippet to it.
- using Microsoft.Owin.Security.OAuth;
- using OauthApi.Models;
- using System;
- using System.Linq;
- using System.Security.Claims;
- using System.Threading.Tasks;
-
- namespace OauthApi.Provider
- {
- public class OauthProvider : OAuthAuthorizationServerProvider
- {
- public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
- {
- await Task.Run(() => context.Validated());
- }
-
- public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
- {
- var identity = new ClaimsIdentity(context.Options.AuthenticationType);
-
- using (var db = new DataContext())
- {
- if (db != null)
- {
- var user = db.ApiUsers.Where(o => o.UserName == context.UserName && o.UserPasswd == context.Password).FirstOrDefault();
- if (user != null)
- {
- identity.AddClaim(new Claim(ClaimTypes.Role, user.UserRole));
- identity.AddClaim(new Claim(ClaimTypes.Name, user.UserName));
- identity.AddClaim(new Claim("LoggedOn", DateTime.Now.ToString()));
- await Task.Run(() => context.Validated(identity));
- }
- else
- {
- context.SetError("Wrong Crendtials", "Provided username and password is incorrect");
- }
- }
- else
- {
- context.SetError("Wrong Crendtials", "Provided username and password is incorrect");
- }
- return;
- }
- }
- }
- }
In the above code the "OauthProvider" class inherits from
class "OAuthAuthorizationServerProvider", we’ve overridden two methods
"ValidateClientAuthentication" and "GrantResourceOwnerCredentials". The
"ValidateClientAuthentication" method is responsible for validating the
"Client" and the "GrantResourceOwnerCredentials" method is responsible to
validate the username and password sent to the authorization server’s token
endpoint.
Step 3: Modify Web
API Controller
Now we will add an action method "GetValues" to
"ValueController" so that we can check the Token-Based Authentication is
working fine or not. To do that open the ValueController and add the below
action method to it.
-
- [Authorize(Roles = "SuperAdmin, Admin, User")]
- [HttpGet]
- [Route("api/values/getvalues")]
- public IHttpActionResult GetValues()
- {
- var identity = (ClaimsIdentity)User.Identity;
- var roles = identity.Claims
- .Where(c => c.Type == ClaimTypes.Role).Select(c => c.Value);
- var LogTime = identity.Claims
- .FirstOrDefault(c => c.Type == "LoggedOn").Value;
- return Ok("Hello: " + identity.Name + ", " +
- "Your Role(s) are: " + string.Join(",", roles.ToList()) +
- "Your Login time is :" + LogTime);
- }
Testing the Web API Application.
To test this first, you need to run your Web API
application. Here I am using a client tool called Postman to test web API.
Step 4.1: Test
without Access Token
Open the Postman application and provide the necessary
details as given in the below image.
Here we will get 401 unauthorized responses.
Step 4.2: Create the
Access Token
First we try to create Access Token with invalid credentials.
Here we will get status as 400 Bad Request and also get the
error describing that the provided username and password are incorrect. Let’s
generate the access token with valid credentials as shown in the below image.
Now we will get status code 200 Ok and access token value,
token type as Bearer and the token expire time in seconds in the Response
section.
Step 4.3: Test with
Access Token
Copy the access token and use it as shown in the below
image.
If all is correct we’ll receive HTTP status 200 along with
the secured data in the response body.
In this article we will learn how to create Access Token and
how to use it using Token Based Authentication. Hope this article will help the readers. Happy Coding!!!