Authentication is a vital process in system programming. Authentication means verifying the user who is accessing the system. Today we are using modern devices that have different types of Apps or software and sometimes we directly access the website from browser. To access this application, we probably need to pass our credentials and these systems verify it. If you are valid user then it will allow accessing the system otherwise not.
We have available different types of authentication in .Net programming like Windows Authentication, Forms Authentication, Claim Based Authentication, Token Based Authentication etc. Today we will discuss about Token Based Authentication in detail.
Token Based Authentication is not very different from other authentication mechanism but yes, it is more secure, more reliable and makes your system loosely coupled. It will be a better choice to create REST API using token-based authentication, if your API reached to broad range of devices like mobiles, tablets and traditional desktops.
In token-based authentication, you pass your credentials [user name and password], which go to authentication server. Server verifies your credentials and if it is a valid user then it will return a signed token to client system, which has expiration time. Client can store this token to locally using any mechanism like local storage, session storage etc and if client makes any other call to server for data then it does not need to pass its credentials every time. Client can directly pass token to server, which will be validated by server and if token is valid then you will able to access your data.
Using the code
In this demonstration, we will use Web API as a service and Angular JS as a client. So, let me create dummy database “Test” and two tables “Users” and “Employee” respectively. Users table will store the user related information like name, username and password. Employee table is basically for dummy data. You can use following SQL scripts to generate this database and tables.
SQL
CREATE DATABASE TEST GO USE TEST GO CREATE TABLE Users(Id INT IDENTITY(1,1) PRIMARY KEY, Name varchar(255) NOT NULL, UserName varchar(50), Password varchar(50)) INSERT INTO [TEST].[dbo].[Users](Name, UserName, Password) VALUES('Sachin', 'sachin', 'sachin123'); CREATE TABLE Employees(Id INT IDENTITY(1,1) PRIMARY KEY, Name varchar(255) NOT NULL, Address varchar(500)) INSERT INTO Employees (Name, Address) VALUES('John Right', 'England') INSERT INTO Employees (Name, Address) VALUES('Chris Roy', 'France') INSERT INTO Employees (Name, Address) VALUES('Anand Mahajan', 'Canada') INSERT INTO Employees (Name, Address) VALUES('Prince Singh', 'India')
Move to next and create a service that will implement token-based authentication. So, going to create a Web API project and for client application we will use Angular JS from where we will pass user credentials.
To create Web API project, first open Visual Studio 2015 and go to File menu and select New and then Project. It will open a New Project windows, select Web from Installed Template and then from right pane, choose “Asp.Net Web Application”. Provide the name like “EmployeeService” and click to OK.
Next windows will provide you options to choose web application template. Here you need to choose Web API with No Authentication and click to OK. Therefore, your application is ready to run.
Before moving next, to implement token-based authentication, we have to add following packages as a references from NuGet Package Manager. So, just right click on references in solution and select Manage NuGet Packages. It will open a NuGet Package Manager windows, you can search these packages one by one from search box in Browse tab. Once these packages are able to find out in NuGet click to Install. After Installtion, these packages will be available in references.
- Microsoft.Owin
- Microsoft.Owin.Host.SystemWeb
- Microsoft.Owin.Security.OAuth
- Microsoft.Owin.Security
- Microsoft.AspNet.Identity.Owin
In this demonstration, we will not use Global.asax file. So, first, delete the Global.asax from solution and add new class “Startup.cs” at the same location of Global.asax file and add following code.
C#
using EmployeeService.Provider; using Microsoft.Owin; using Microsoft.Owin.Security.OAuth; using Owin; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Http; [assembly: OwinStartup(typeof(EmployeeService.Startup))] namespace EmployeeService { public class Startup { public void ConfigureAuth(IAppBuilder app) { var OAuthOptions = new OAuthAuthorizationServerOptions { AllowInsecureHttp = true, TokenEndpointPath = new PathString("/token"), AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(20), Provider = new SimpleAuthorizationServerProvider() }; app.UseOAuthBearerTokens(OAuthOptions); app.UseOAuthAuthorizationServer(OAuthOptions); app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()); HttpConfiguration config = new HttpConfiguration(); WebApiConfig.Register(config); } public void Configuration(IAppBuilder app) { ConfigureAuth(app); GlobalConfiguration.Configure(WebApiConfig.Register); } } }
In the above code, you can see, we are using OWIN [Open Web Interface for .Net] that is an interface between your web server and web application. So, it works as a middle ware in applications, which process your incoming request and validate it. Here we are using SimpleAuthorizationServerProvider, which is nothing but a class which validate user based on their credentials. You can find this class code at the last.
Now it’s time to create a model where we can perform database operation like fetching the user information based on credentials and employees data. We can use here different ways to get data like Repository pattern with Unit of work or Dapper. But we want to make this example simple and keep the main focus on Token Based Authentication only. So, right click on solution and Click to Add and then New Item and choose Ado.Net Entity Model.
Ref: https://code.msdn.microsoft.com/Token-Based-Authentication-6db2acc9
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.OAuth;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Web.Http.Cors;
namespace EmployeeService.Provider
{
[EnableCors(origins: "*", headers: "*", methods: "*")]
public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated(); //
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
using (var db = new TESTEntities())
{
if (db != null)
{
var empl = db.Employees.ToList();
var user = db.Users.ToList();
if (user != null)
{
if (!string.IsNullOrEmpty(user.Where(u => u.UserName == context.UserName && u.Password == context.Password).FirstOrDefault().Name))
{
identity.AddClaim(new Claim("Age", "16"));
var props = new AuthenticationProperties(new Dictionary<string, string>
{
{
"userdisplayname", context.UserName
},
{
"role", "admin"
}
});
var ticket = new AuthenticationTicket(identity, props);
context.Validated(ticket);
}
else
{
context.SetError("invalid_grant", "Provided username and password is incorrect");
context.Rejected();
}
}
}
else
{
context.SetError("invalid_grant", "Provided username and password is incorrect");
context.Rejected();
}
return;
}
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
namespace EmployeeService.Controllers
{
public class EmployeeController : ApiController
{
[HttpGet]
[Authorize]
public List<Employee> GetEmployees()
{
using (var db = new TESTEntities())
{
var employees = db.Employees.ToList();
return employees;
}
}
}
}
using Microsoft.Owin;
using Microsoft.Owin.Security.OAuth;
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
[assembly: OwinStartup(typeof(EmployeeService.Startup))]
namespace EmployeeService
{
public class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
var OAuthOptions = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(20),
Provider = new SimpleAuthorizationServerProvider()
};
app.UseOAuthBearerTokens(OAuthOptions);
app.UseOAuthAuthorizationServer(OAuthOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
}
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
GlobalConfiguration.Configure(WebApiConfig.Register);
}
}
}
Comments
Post a Comment