Token Based Authentication Using Web API 2: Part 2

This is my second article on the Web API Token. As we have seen in the first article, in this article I will try to primarily focus on Token generation, refresh token generation and authorization using the generated token. We have already learned about the OAuthorizationServerOptions. We will again learn in another way, this time we will cover all these things in a web based MVC API application using Knockout js. So let's try to learn step-by-step.

Prerequisites  

  • Visual Studio 2013
  • SQL Server

Step 1

Start Visual Studio 2013 and select a new project.

StartANewProject

Step 2

Choose the Web API template along with MVC and check that the Authentication type would be Individual User Account.

WebAPI_Template 

Step 3

Now we can move to the coding part, so before we do the coding, let's try to understand some basic concepts or terminology used in OAuth 2. They are the following.

  • Resource Owner
  • Resource Server
  • Access Token
  • Bearer Token

Bearer Token

This is a type of access specifier used to authenticate the user. Bearer tokens are only used over HTTPS.

Access Token

An Access Token is a token that grants the access of resources.

Resource Server

A server that hosts the resources.

Resource Owner

Resource owners are those that can get access to the resource (a user).

Now flip into the Visual Studio 2013 and open the Starup.Auth.cs file. In the pre-generated code we can see there is a Token field. Now we can additionally call the Refresh Token. Let's see.

refrshToken

Use the Microsoft.Owin.Security.Infrstructure namespace in the project. Apart from that we need to also define the OnCreate and OnRecieve methods for the RefereshToken. See the following code.

  1. public void ConfigureAuth(IAppBuilder app)  
  2.     {  
  3.         app.CreatePerOwinContext(ApplicationDbContext.Create);  
  4.         app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);  
  5.         app.UseCookieAuthentication(new CookieAuthenticationOptions());  
  6.        // app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);  
  7.         PublicClientId = "self";  
  8.         OAuthOptions = new OAuthAuthorizationServerOptions  
  9.         {  
  10.             TokenEndpointPath = new PathString("/Token"),  
  11.             Provider = new ApplicationOAuthProvider(PublicClientId),  
  12.             RefreshTokenProvider = new AuthenticationTokenProvider()  
  13.             {  
  14.                 OnCreate = CreateRefreshToken,  
  15.                 OnReceive = RecieveRefreshToken  
  16.             },  
  17.             AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),  
  18.             AccessTokenExpireTimeSpan = TimeSpan.FromDays(10),  
  19.             AllowInsecureHttp = true,  
  20.   
  21.         };  
  22.   
  23.         app.UseOAuthBearerTokens(OAuthOptions);  
  24.     }  
  25.   
  26.     private static void RecieveRefreshToken(AuthenticationTokenReceiveContext obj)  
  27.     {  
  28.         //throw new NotImplementedException();  
  29.         obj.DeserializeTicket(obj.Token);  
  30.     }  
  31.   
  32.     private static void CreateRefreshToken(AuthenticationTokenCreateContext obj)  
  33.     {  
  34.         // throw new NotImplementedException();  
  35.         obj.SetToken(obj.SerializeTicket());  
  36.     }  

Step 4

Install the Knockout.js from Nuget.

knockoutjs

Step 5

Make an App.Js file. 

  1. function ViewModel() {  
  2.     var self = this;  
  3.   
  4.     var tokenKey = 'accessToken';  
  5.     var RefTokenKey = 'refreshToken';  
  6.     self.result = ko.observable();  
  7.     self.user = ko.observable();  
  8.   
  9.     self.registerEmail = ko.observable();  
  10.     self.registerPassword = ko.observable();  
  11.     self.registerPassword2 = ko.observable();  
  12.   
  13.     self.loginEmail = ko.observable();  
  14.     self.loginPassword = ko.observable();  
  15.     self.token = ko.observable();  
  16.     self.refreshToken = ko.observable();  
  17.     function showError(jqXHR) {  
  18.         self.result(jqXHR.status + ': ' + jqXHR.statusText);  
  19.     }  
  20.   
  21.     self.callApi = function () {  
  22.   
  23.         self.result('');  
  24.   
  25.         var token = sessionStorage.getItem(tokenKey);  
  26.   
  27.         var headers = {};  
  28.         if (token) {  
  29.             headers.Authorization = 'Bearer ' + token;  
  30.         }  
  31.   
  32.         $.ajax({  
  33.             type: 'GET',  
  34.             url: '/api/values',  
  35.             headers: headers  
  36.         }).done(function (data) {  
  37.             self.result(data);  
  38.         }).fail(showError);  
  39.     }  
  40.   
  41.     self.callToken = function () {  
  42.         self.result('');  
  43.         // alert(self.loginEmail());  
  44.         // alert(self.loginPassword());  
  45.         var loginData = {  
  46.             grant_type: 'password',  
  47.             username: self.loginEmail(),  
  48.             password: self.loginPassword()  
  49.         };  
  50.   
  51.         $.ajax({  
  52.             type: 'POST',  
  53.             url: '/Token',  
  54.             data: loginData  
  55.         }).done(function (data) {  
  56.             self.user(data.userName);  
  57.             // Cache the access token in session storage.  
  58.             sessionStorage.setItem(tokenKey, data.access_token);  
  59.             var tkn = sessionStorage.getItem(tokenKey);  
  60.             $("#tknKey").val(tkn);  
  61.         }).fail(showError);  
  62.     }  
  63.   
  64. }  
  65.   
  66. var app = new ViewModel();  
  67. ko.applyBindings(app);  

Step 6

Open the Index page and design the registration and login form. So for that we can see the authorization using a token, also we can see the generated token and refresh token too. 

  1. @section Scripts {  
  2.     @Scripts.Render("~/bundles/App")  
  3. }  
  4. <div class="row alert-danger breadcrumb">  
  5.     <div class="col-sm-6">  
  6.         <form data-bind="submit: callApi">  
  7.             <h3>Invoke API</h3>  
  8.             <div class="form-group">  
  9.                 <label>User</label>  
  10.                 <input class="form-control" type="text" readonly data-bind="value: user" />  
  11.             </div>  
  12.             <div class="form-group">  
  13.                 <label>Result</label>  
  14.                 <input class="form-control" type="text" readonly data-bind="value: result" />  
  15.   
  16.             </div>  
  17.             <div class="form-group">  
  18.                 <button type="submit" class="btn btn-default">Call API</button>  
  19.             </div>  
  20.         </form>  
  21.     </div>  
  22. </div>  

Step 7

Now flip into the BundleConfig.cs file and add the App.js file inside it.

BundleConfigSetting

Step 8

Call that bundle App.js file inside the Index page.

Now we can use the token-based authentication.

final Report

Now we can use any resource, if the resource is in " [Authorize]" using these tokens. If the token is wrong or expired then that resource will not allow us to use it. 

Next Recommended Readings