ASP.NET MVC - OAuth 2.0 REST Web API Authorization Using Database First Approach

This article is about OAuth 2.0 authorization scheme integration with ASP.NET MVC REST Web API.

REST Web API is a light-weight essential component of web development in order to share the data across multiple client machines or devices e.g. mobile devices, desktop applications or any website. Authorization of REST Web API is an equally important part for sharing data across multiple client machines and devices in order to protect data sensitivity from any outside breaches and to authenticate the utilization of the target REST Web API.

Authorization of REST Web API can be done via a specific username/password with the combination of a secret key, but, for this type of authorization scheme, REST Web API access needs to be authenticated per call to the hosting server. Also, we as the owner of the server have no way to verify who is utilizing our REST Web API, whether it's the clients that we have allowed access to or if some malicious user is also using our API(s) without our knowledge. Finally, since the username/password is packed to a base64 format automatically by the browser, if any malicious user traces my browser activity and gets ahold of my REST Web API calls they can easily decrypt base64 format and could use my REST Web API for malicious activities.

Hmmmmm.....scary stuff! Not to mention that despite the fact that I have authorized my REST Web API, it is still open for malicious users to utilize without even my knowledge. So, what to do? To answer that a new authorization scheme is introduced which can also be utilized in Login flow of any web application as well, but, I will be focusing on it from a REST Web API perspective. So, this new scheme of authorization is OAuth 2.0 which is a token based authorization scheme.

Let's compare OAuth 2.0 authorization scheme to the traditional username/password authorization scheme from REST Web API perspective, i.e.,

Username/Password REST Web API Authorization
VS
OAuth 2.0 REST Web API Authorization
1.
Access Authorization to same or different REST Web API(s) on the same server is authenticated on each call with provided username/password.
Access Authorization is authenticated only once based on the system’s existing user credential, then on successful authorization, an access token is provided for a specific period of time. REST Web API(s) call can utilize the access token which server will not authenticate again and again.
2.
REST Web API(s) call cannot track the user who is consuming the REST Web API(s). Its utilization is based on mutual trust between Producer and consumer.
Only local system users can consume the REST Web API(s), so, REST Web API call can track the user who is consuming the REST Web API.
3.
Username/Password is encrypted in base64 format. So, hackers can easily decrypt the request headers.
Access Token is encrypted in a special format. So, hackers cannot easily decrypt it even with access to request header.
4.
All client machines or devices code needs to be updated in case of the change in username/password for malicious activities.
Access token is activated for a specific time period. Change in system user’s credential will not require the change of code in target consumer client machines and devices. Update credential generated a new access token.
5.
Username/Password is fixed.
Access token is generated automatically based on system user’s credential.

Today, I shall demonstrate OAuth 2.0 mechanism to authorize a REST Web API which will also give us the benefit of [Authorize] attribute via OWIN security layer.

Following are a few prerequisites before you proceed any further,

  1. Knowledge of OAuth 2.0.
  2. Knowledge of ASP.NET MVC5.
  3. Knowledge of C# programming.
  4. Knowledge of REST Web API.

You can download the complete source code or you can follow the step by step discussion below. The sample code is developed in Microsoft Visual Studio 2015 Enterprise.

Let's begin now:

Step 1

Create a new Web API project and name it "WebApiOauth2".

Step 2

Install the following NuGet packages into your project, i.e.,

  1. Microsoft.Owin.Security.OAuth
  2. Microsoft.Owin.Cors
  3. Microsoft.AspNet.WebApi.Core
  4. Microsoft.AspNet.WebApi.Owin

Step 3

Create "DB_Oauth_API" database into your SQL Server and execute the following script on it, i.e.,

  1. USE [DB_Oauth_API]  
  2. GO  
  3. /****** Object:  StoredProcedure [dbo].[LoginByUsernamePassword]    Script Date: 5/10/2018 2:37:02 PM ******/  
  4. DROP PROCEDURE [dbo].[LoginByUsernamePassword]  
  5. GO  
  6. /****** Object:  Table [dbo].[Login]    Script Date: 5/10/2018 2:37:02 PM ******/  
  7. DROP TABLE [dbo].[Login]  
  8. GO  
  9. /****** Object:  Table [dbo].[Login]    Script Date: 5/10/2018 2:37:02 PM ******/  
  10. SET ANSI_NULLS ON  
  11. GO  
  12. SET QUOTED_IDENTIFIER ON  
  13. GO  
  14. SET ANSI_PADDING ON  
  15. GO  
  16. CREATE TABLE [dbo].[Login](  
  17.     [id] [int] IDENTITY(1,1) NOT NULL,  
  18.     [username] [varchar](50) NOT NULL,  
  19.     [password] [varchar](50) NOT NULL,  
  20.  CONSTRAINT [PK_Login] PRIMARY KEY CLUSTERED   
  21. (  
  22.     [id] ASC  
  23. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ONON [PRIMARY]  
  24. ON [PRIMARY]  
  25.   
  26. GO  
  27. SET ANSI_PADDING OFF  
  28. GO  
  29. SET IDENTITY_INSERT [dbo].[Login] ON   
  30.   
  31. INSERT [dbo].[Login] ([id], [username], [password]) VALUES (1, N'admin', N'adminpass')  
  32. SET IDENTITY_INSERT [dbo].[Login] OFF  
  33. /****** Object:  StoredProcedure [dbo].[LoginByUsernamePassword]    Script Date: 5/10/2018 2:37:02 PM ******/  
  34. SET ANSI_NULLS ON  
  35. GO  
  36. SET QUOTED_IDENTIFIER ON  
  37. GO  
  38. -- =============================================  
  39. -- Author:      <Author,,Asma Khalid>  
  40. -- Create date: <Create Date,,15-Mar-2016>  
  41. -- Description: <Description,,You are Allow to Distribute this Code>  
  42. -- =============================================  
  43. CREATE PROCEDURE [dbo].[LoginByUsernamePassword]   
  44.     @username varchar(50),  
  45.     @password varchar(50)  
  46. AS  
  47. BEGIN  
  48.     SELECT id, username, password  
  49.     FROM Login  
  50.     WHERE username = @username  
  51.     AND password = @password  
  52. END  
  53.   
  54. GO 
In the above script, I have created a simple login table and a stored procedure to retrieve the specific login. I am using entity framework database first approach for database connection for this ASP.NET MVC WebAPI application. Do also update your SQL server connection string in the project "Web.config" file if you have downloaded the project i.e.

 

Step 4

Rename "Controllers/ValueController.cs" file to "Controllers/WebApiController.cs".

Step 5

Open, "Controllers/WebApiController.cs" file replace following code,

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Net;  
  5. using System.Net.Http;  
  6. using System.Web.Http;  
  7.   
  8. namespace WebApiOauth2.Controllers  
  9. {  
  10.     [Authorize]  
  11.     public class WebApiController : ApiController  
  12.     {  
  13.         // GET api/WebApi  
  14.         public IEnumerable<string> Get()  
  15.         {  
  16.             return new string[] { "Hello REST API""I am Authorized" };  
  17.         }  
  18.   
  19.         // GET api/WebApi/5  
  20.         public string Get(int id)  
  21.         {  
  22.             return "Hello Authorized API with ID = " + id;  
  23.         }  
  24.   
  25.         // POST api/WebApi  
  26.         public void Post([FromBody]string value)  
  27.         {  
  28.         }  
  29.   
  30.         // PUT api/WebApi/5  
  31.         public void Put(int id, [FromBody]string value)  
  32.         {  
  33.         }  
  34.   
  35.         // DELETE api/WebApi/5  
  36.         public void Delete(int id)  
  37.         {  
  38.         }  
  39.     }  

In the above code, I have created very simple and basic REST Web API(s). Notice [Authorize] attribute is already placed at the top of the controller to make the REST Web API(s) access secure.

Step 6

Now open "App_Start/WebApiConfig.cs" file and replace the following code in it i.e.

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web.Http;  
  5. using Microsoft.Owin.Security.OAuth;  
  6.   
  7. namespace WebApiOauth2  
  8. {  
  9.     public static class WebApiConfig  
  10.     {  
  11.         public static void Register(HttpConfiguration config)  
  12.         {  
  13.             // Web API configuration and services  
  14.             // Configure Web API to use only bearer token authentication.  
  15.             config.SuppressDefaultHostAuthentication();  
  16.             config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));  
  17.   
  18.             // Web API routes  
  19.             config.MapHttpAttributeRoutes();  
  20.   
  21.             config.Routes.MapHttpRoute(  
  22.                 name: "DefaultApi",  
  23.                 routeTemplate: "api/{controller}/{id}",  
  24.                 defaults: new { id = RouteParameter.Optional }  
  25.             );  
  26.   
  27.             // WebAPI when dealing with JSON & JavaScript!  
  28.             // Setup json serialization to serialize classes to camel (std. Json format)  
  29.             var formatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter;  
  30.             formatter.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();  
  31.   
  32.             // Adding JSON type web api formatting.  
  33.             config.Formatters.Clear();  
  34.             config.Formatters.Add(formatter);  
  35.         }  
  36.     }  

In the above code the following two lines of code will add authentication filter for Oauth 2.0 authorization scheme and surpass any existing authorization scheme i.e.

  1. surpass any existing authorization scheme i.e.  
  2.             // Web API configuration and services  
  3.             // Configure Web API to use only bearer token authentication.  
  4.             config.SuppressDefaultHostAuthentication();  
  5.             config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); 

Step 7

Now, open "App_Start/Startup.Auth.cs" file and replace following code in it i.e.

  1. using System;  
  2. using Microsoft.AspNet.Identity;  
  3. using Microsoft.AspNet.Identity.Owin;  
  4. using Microsoft.Owin;  
  5. using Microsoft.Owin.Security.Cookies;  
  6. using Microsoft.Owin.Security.Google;  
  7. using Owin;  
  8. using WebApiOauth2.Models;  
  9. using Microsoft.Owin.Security.OAuth;  
  10. using WebApiOauth2.Helper_Code.OAuth2;  
  11.   
  12. namespace WebApiOauth2  
  13. {  
  14.     public partial class Startup  
  15.     {  
  16.         #region Public /Protected Properties.  
  17.   
  18.         /// <summary>  
  19.         /// OAUTH options property.  
  20.         /// </summary>  
  21.         public static OAuthAuthorizationServerOptions OAuthOptions { getprivate set; }  
  22.   
  23.         /// <summary>  
  24.         /// Public client ID property.  
  25.         /// </summary>  
  26.         public static string PublicClientId { getprivate set; }  
  27.  
  28.         #endregion  
  29.   
  30.         // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864  
  31.         public void ConfigureAuth(IAppBuilder app)  
  32.         {  
  33.             // Enable the application to use a cookie to store information for the signed in user  
  34.             // and to use a cookie to temporarily store information about a user logging in with a third party login provider  
  35.             // Configure the sign in cookie  
  36.             app.UseCookieAuthentication(new CookieAuthenticationOptions  
  37.             {  
  38.                 AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,  
  39.                 LoginPath = new PathString("/Account/Login"),  
  40.                 LogoutPath = new PathString("/Account/LogOff"),  
  41.                 ExpireTimeSpan = TimeSpan.FromMinutes(5.0),  
  42.             });   
  43.                          
  44.             app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);  
  45.   
  46.             // Configure the application for OAuth based flow  
  47.             PublicClientId = "self";  
  48.             OAuthOptions = new OAuthAuthorizationServerOptions  
  49.             {  
  50.                 TokenEndpointPath = new PathString("/Token"),  
  51.                 Provider = new AppOAuthProvider(PublicClientId),  
  52.                 AuthorizeEndpointPath = new PathString("/Account/ExternalLogin"),  
  53.                 AccessTokenExpireTimeSpan = TimeSpan.FromHours(4),  
  54.                 AllowInsecureHttp = true //Don't do this in production ONLY FOR DEVELOPING: ALLOW INSECURE HTTP!  
  55.             };  
  56.   
  57.             // Enable the application to use bearer tokens to authenticate users  
  58.             app.UseOAuthBearerTokens(OAuthOptions);  
  59.   
  60.             // Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.  
  61.             app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));  
  62.   
  63.             // Enables the application to remember the second login verification factor such as phone or email.  
  64.             // Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.  
  65.             // This is similar to the RememberMe option when you log in.  
  66.             app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);  
  67.   
  68.             // Uncomment the following lines to enable logging in with third party login providers  
  69.             //app.UseMicrosoftAccountAuthentication(  
  70.             //    clientId: "",  
  71.             //    clientSecret: "");  
  72.   
  73.             //app.UseTwitterAuthentication(  
  74.             //   consumerKey: "",  
  75.             //   consumerSecret: "");  
  76.   
  77.             //app.UseFacebookAuthentication(  
  78.             //   appId: "",  
  79.             //   appSecret: "");  
  80.   
  81.             //app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()  
  82.             //{  
  83.             //    ClientId = "",  
  84.             //    ClientSecret = ""  
  85.             //});  
  86.         }  
  87.     }  

In the above piece of code, "PublicClientId" is used when "AuthorizeEndpointPath" is utilized for unique instantiation from client-side. Following lines of code will enable the OAuth 2.0 authorization scheme, i.e.

  1. from client side. Following lines of code will enable the OAuth 2.0 authorization scheme i.e.  
  2.             // Configure the application for OAuth based flow  
  3.             PublicClientId = "self";  
  4.             OAuthOptions = new OAuthAuthorizationServerOptions  
  5.             {  
  6.                 TokenEndpointPath = new PathString("/Token"),  
  7.                 Provider = new AppOAuthProvider(PublicClientId),  
  8.                 AuthorizeEndpointPath = new PathString("/Account/ExternalLogin"),  
  9.                 AccessTokenExpireTimeSpan = TimeSpan.FromHours(4),  
  10.                 AllowInsecureHttp = true //Don't do this in production ONLY FOR DEVELOPING: ALLOW INSECURE HTTP!  
  11.             };  
  12.   
  13.             // Enable the application to use bearer tokens to authenticate users  
  14.             app.UseOAuthBearerTokens(OAuthOptions); 

OAuthAuthorizationOptions are explained as follow i.e.

  • TokenEndpointPath ->
    This is the path which will be called in order to authorize the user credentials and in return it will return the generated access token.

  • Provider ->
    You need to implement this class (which I have in this tutorial) where you will verify the user credential and create identity claims in order to return the generated access token.

  • AuthorizeEndpointPath ->
    In this tutorial, I am not using this property as I am not taking consent of external logins. So, if you are using external logins then you can update this path to get user consent then required access token will be generated.

  • AccessTokenExpireTimeSpan ->
    This is the time period you want your access token to be accessible. The shorter time span is recommended for sensitive API(s).

  • AllowInsecureHttp ->
    Use this property for developer environment.

 

More properties can be studied here.

Step 8

Now, create "Helper_Code/OAuth2/AppOAuthProvider.cs" file and replace following code in it i.e.

  1. //-----------------------------------------------------------------------  
  2. // <copyright file="AppOAuthProvider.cs" company="None">  
  3. //     Copyright (c) Allow to distribute this code.  
  4. // </copyright>  
  5. // <author>Asma Khalid</author>  
  6. //-----------------------------------------------------------------------  
  7.   
  8. namespace WebApiOauth2.Helper_Code.OAuth2  
  9. {  
  10.     using Microsoft.Owin.Security;  
  11.     using Microsoft.Owin.Security.Cookies;  
  12.     using Microsoft.Owin.Security.OAuth;  
  13.     using Models;  
  14.     using System;  
  15.     using System.Collections.Generic;  
  16.     using System.Linq;  
  17.     using System.Security.Claims;  
  18.     using System.Threading.Tasks;  
  19.     using System.Web;  
  20.   
  21.     /// <summary>  
  22.     /// Application OAUTH Provider class.  
  23.     /// </summary>  
  24.     public class AppOAuthProvider : OAuthAuthorizationServerProvider  
  25.     {  
  26.         #region Private Properties  
  27.   
  28.         /// <summary>  
  29.         /// Public client ID property.  
  30.         /// </summary>  
  31.         private readonly string _publicClientId;  
  32.   
  33.         /// <summary>  
  34.         /// Database Store property.  
  35.         /// </summary>  
  36.         private Oauth_APIEntities databaseManager = new Oauth_APIEntities();  
  37.  
  38.         #endregion  
  39.  
  40.         #region Default Constructor method.  
  41.   
  42.         /// <summary>  
  43.         /// Default Constructor method.  
  44.         /// </summary>  
  45.         /// <param name="publicClientId">Public client ID parameter</param>  
  46.         public AppOAuthProvider(string publicClientId)  
  47.         {  
  48.             //TODO: Pull from configuration  
  49.             if (publicClientId == null)  
  50.             {  
  51.                 throw new ArgumentNullException(nameof(publicClientId));  
  52.             }  
  53.   
  54.             // Settings.  
  55.             _publicClientId = publicClientId;  
  56.         }  
  57.  
  58.         #endregion  
  59.  
  60.         #region Grant resource owner credentials override method.  
  61.   
  62.         /// <summary>  
  63.         /// Grant resource owner credentials overload method.  
  64.         /// </summary>  
  65.         /// <param name="context">Context parameter</param>  
  66.         /// <returns>Returns when task is completed</returns>  
  67.         public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)  
  68.         {  
  69.             // Initialization.  
  70.             string usernameVal = context.UserName;  
  71.             string passwordVal = context.Password;  
  72.             var user = this.databaseManager.LoginByUsernamePassword(usernameVal, passwordVal).ToList();  
  73.   
  74.             // Verification.  
  75.             if (user == null || user.Count() <= 0)  
  76.             {  
  77.                 // Settings.  
  78.                 context.SetError("invalid_grant""The user name or password is incorrect.");  
  79.   
  80.                 // Retuen info.  
  81.                 return;  
  82.             }  
  83.   
  84.             // Initialization.  
  85.             var claims = new List<Claim>();  
  86.             var userInfo = user.FirstOrDefault();  
  87.   
  88.             // Setting  
  89.             claims.Add(new Claim(ClaimTypes.Name, userInfo.username));  
  90.   
  91.             // Setting Claim Identities for OAUTH 2 protocol.  
  92.             ClaimsIdentity oAuthClaimIdentity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType);  
  93.             ClaimsIdentity cookiesClaimIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationType);  
  94.   
  95.             // Setting user authentication.  
  96.             AuthenticationProperties properties = CreateProperties(userInfo.username);  
  97.             AuthenticationTicket ticket = new AuthenticationTicket(oAuthClaimIdentity, properties);  
  98.   
  99.             // Grant access to authorize user.  
  100.             context.Validated(ticket);  
  101.             context.Request.Context.Authentication.SignIn(cookiesClaimIdentity);  
  102.         }  
  103.  
  104.         #endregion  
  105.  
  106.         #region Token endpoint override method.  
  107.   
  108.         /// <summary>  
  109.         /// Token endpoint override method  
  110.         /// </summary>  
  111.         /// <param name="context">Context parameter</param>  
  112.         /// <returns>Returns when task is completed</returns>  
  113.         public override Task TokenEndpoint(OAuthTokenEndpointContext context)  
  114.         {  
  115.             foreach (KeyValuePair<stringstring> property in context.Properties.Dictionary)  
  116.             {  
  117.                 // Adding.  
  118.                 context.AdditionalResponseParameters.Add(property.Key, property.Value);  
  119.             }  
  120.   
  121.             // Return info.  
  122.             return Task.FromResult<object>(null);  
  123.         }  
  124.  
  125.         #endregion  
  126.  
  127.         #region Validate Client authntication override method  
  128.   
  129.         /// <summary>  
  130.         /// Validate Client authntication override method  
  131.         /// </summary>  
  132.         /// <param name="context">Contect parameter</param>  
  133.         /// <returns>Returns validation of client authentication</returns>  
  134.         public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)  
  135.         {  
  136.             // Resource owner password credentials does not provide a client ID.  
  137.             if (context.ClientId == null)  
  138.             {  
  139.                 // Validate Authoorization.  
  140.                 context.Validated();  
  141.             }  
  142.   
  143.             // Return info.  
  144.             return Task.FromResult<object>(null);  
  145.         }  
  146.  
  147.         #endregion  
  148.  
  149.         #region Validate client redirect URI override method  
  150.   
  151.         /// <summary>  
  152.         /// Validate client redirect URI override method  
  153.         /// </summary>  
  154.         /// <param name="context">Context parmeter</param>  
  155.         /// <returns>Returns validation of client redirect URI</returns>  
  156.         public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)  
  157.         {  
  158.             // Verification.  
  159.             if (context.ClientId == _publicClientId)  
  160.             {  
  161.                 // Initialization.  
  162.                 Uri expectedRootUri = new Uri(context.Request.Uri, "/");  
  163.   
  164.                 // Verification.  
  165.                 if (expectedRootUri.AbsoluteUri == context.RedirectUri)  
  166.                 {  
  167.                     // Validating.  
  168.                     context.Validated();  
  169.                 }  
  170.             }  
  171.   
  172.             // Return info.  
  173.             return Task.FromResult<object>(null);  
  174.         }  
  175.  
  176.         #endregion  
  177.  
  178.         #region Create Authentication properties method.  
  179.   
  180.         /// <summary>  
  181.         /// Create Authentication properties method.  
  182.         /// </summary>  
  183.         /// <param name="userName">User name parameter</param>  
  184.         /// <returns>Returns authenticated properties.</returns>  
  185.         public static AuthenticationProperties CreateProperties(string userName)  
  186.         {  
  187.             // Settings.  
  188.             IDictionary<stringstring> data = new Dictionary<stringstring>  
  189.                                                {  
  190.                                                    { "userName", userName }  
  191.                                                };  
  192.   
  193.             // Return info.  
  194.             return new AuthenticationProperties(data);  
  195.         }  
  196.  
  197.         #endregion  
  198.     }  

In the above code, "GrantResourceOwnerCredentials(...)" method is the key method which is called when TokenEndpointPath is called. Notice that "GrantResourceOwnerCredentials(...)" method is used by "grant_type=password" scheme. If you are using "grant_type=client_credentials" scheme then you need to override "GrantClientCredentials(...)" method. Other methods are part of "OAuthAuthorizationServerProvider" class, use them as they are. In "GrantResourceOwnerCredentials(...)" method we are verifying the system login user and then create the require identities claims and then generate the returning access token ticket i.e.

  1. #region Grant resource owner credentials override method.  
  2.   
  3. /// <summary>  
  4. /// Grant resource owner credentials overload method.  
  5. /// </summary>  
  6. /// <param name="context">Context parameter</param>  
  7. /// <returns>Returns when task is completed</returns>  
  8. public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)  
  9. {  
  10.     // Initialization.  
  11.     string usernameVal = context.UserName;  
  12.     string passwordVal = context.Password;  
  13.     var user = this.databaseManager.LoginByUsernamePassword(usernameVal, passwordVal).ToList();  
  14.   
  15.     // Verification.  
  16.     if (user == null || user.Count() <= 0)  
  17.     {  
  18.         // Settings.  
  19.         context.SetError("invalid_grant""The user name or password is incorrect.");  
  20.   
  21.         // Retuen info.  
  22.         return;  
  23.     }  
  24.   
  25.     // Initialization.  
  26.     var claims = new List<Claim>();  
  27.     var userInfo = user.FirstOrDefault();  
  28.   
  29.     // Setting  
  30.     claims.Add(new Claim(ClaimTypes.Name, userInfo.username));  
  31.   
  32.     // Setting Claim Identities for OAUTH 2 protocol.  
  33.     ClaimsIdentity oAuthClaimIdentity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType);  
  34.     ClaimsIdentity cookiesClaimIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationType);  
  35.   
  36.     // Setting user authentication.  
  37.     AuthenticationProperties properties = CreateProperties(userInfo.username);  
  38.     AuthenticationTicket ticket = new AuthenticationTicket(oAuthClaimIdentity, properties);  
  39.   
  40.     // Grant access to authorize user.  
  41.     context.Validated(ticket);  
  42.     context.Request.Context.Authentication.SignIn(cookiesClaimIdentity);  
  43. }  
  44.  
  45. #endregion 

Step 9

Now, execute the project and use the following link in the browser to see your newly created REST Web API method in action as follows:

  1. yourlink:port/api/WebApi   
In the above snippet, you will notice that since now our REST Web API has been authorized, therefore, we cannot directly execute the REST Web API URL in the browser. 

Step 10

Let's test out REST Web API in REST Web API client. I am using Firefox plugin i.e. "RESTED". At, first, I simply try to hit the REST Web API without any authorization details and I will get following response i.e.


Step 11

Now, I will provide the system user authorization to get access token and then use that access token as a header in the REST Web API and try to his the REST Web API which will return the following response, i.e.


 

 
Notice in the above snippets that access token is provided as "Authorization" header with "Bearer access_token" scheme in order to call the REST Web API. Also, notice the path when the token is being generated i.e. "{your_site_url}/Token".

Conclusion

In this article, you learned about OAuth 2.0 authorization scheme integration with ASP.NET MVC REST Web API. You also learned about the short comparison between user/password based authorization and OAuth 2.0 token based authorization. You also learned about OAuth 2.0 scheme authentication mechanism for local system users with the Entity Framework database first approach.