Skip to main content

Custom - Token Based Authentication in Web API

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,1PRIMARY KEYName varchar(255NOT NULLUserName varchar(50), Password varchar(50)) 
INSERT INTO [TEST].[dbo].[Users](NameUserNamePasswordVALUES('Sachin''sachin''sachin123'); 
 
CREATE TABLE Employees(Id INT IDENTITY(1,1PRIMARY KEYName varchar(255NOT NULLAddress varchar(500))  
INSERT INTO Employees (NameAddressVALUES('John Right''England'INSERT INTO Employees (NameAddressVALUES('Chris Roy''France'INSERT INTO Employees (NameAddressVALUES('Anand Mahajan''Canada'INSERT INTO Employees (NameAddressVALUES('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.
  1. Microsoft.Owin
  2. Microsoft.Owin.Host.SystemWeb
  3. Microsoft.Owin.Security.OAuth
  4. Microsoft.Owin.Security
  5. 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.


    This link code helpful for me
    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 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);
            }
        }
    }


    Comments

    Popular posts from this blog

    C# Generic class to parse value - "GenericConverter"

        public class GenericConverter     {         public static T Parse<T>(string sourceValue) where T : IConvertible         {             return (T)Convert.ChangeType(sourceValue, typeof(T));         }         public static T Parse<T>(string sourceValue, IFormatProvider provider) where T : IConvertible         {             return (T)Convert.ChangeType(sourceValue, typeof(T), provider);         }     }     public static class TConverter     {         public static T ChangeType<T>(object value)         {             return (T)ChangeType(typeof(T), value);         }         public static object ChangeType(Type t, object value)         {             TypeConverter tc = TypeDescriptor.GetConverter(t);             return tc.ConvertFrom(value);         }         public static void RegisterTypeConverter<T, TC>() where TC : TypeConverter         {             TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(typeof(TC)));         }     } ----------------

    How to create a countdown timer in jquery

    Create a countdown timer in jQuery First we need to include the jQuery library file to the HTML page to perform this task. To do that we need to understand that what exactly a jQuery library fie is ? JQuery library file is the library of JavaScript, which means this file contains the predefined functions of jQuery. We just need to call these functions to perform the task. jQuery functions reduces the lines of code and makes our task easy. As this jQuery library file contains the javascript functions so we need to call the function within <script> </script> tag. Now after including the file, we need to define a variable which will store that for how long you want the timer on the page(c=60) and now the time you set needs to be changed in hours , minutes and seconds using the code “ var hours = parseInt( time / 3600 ) % ;var minutes = parseInt( time / 60 ) % 60; var seconds = time % 60;” Now we need to put the condition if timer got finished (if (t

    Tip/Trick: Fix Common SEO Problems Using the URL Rewrite Extension

    Search engine optimization (SEO) is important for any publically facing web-site.  A large % of traffic to sites now comes directly from search engines, and improving your site’s search relevancy will lead to more users visiting your site from search engine queries.  This can directly or indirectly increase the money you make through your site. This blog post covers how you can use the free Microsoft  URL Rewrite Extension  to fix a bunch of common SEO problems that your site might have.  It takes less than 15 minutes (and no code changes) to apply 4 simple  URL Rewrite  rules to your site, and in doing so cause search engines to drive more visitors and traffic to your site.  The techniques below work equally well with both ASP.NET Web Forms and ASP.NET MVC based sites.  They also works with all versions of ASP.NET (and even work with non-ASP.NET content). [In addition to blogging, I am also now using Twitter for quick updates and to share links. Follow me at:  twitter.com/scottg