HI WELCOME TO SIRIS

Token Based Authentication in ASP.NET Web API

ASP.NET Web API is a service which can be accessed over the HTTP by any client. So, providing the security to the Web API is very important, which can be easily done with the process called Token based authentication. Token-based authentication is a process where the user send his credential to the server, server will validate the user details and generate a token which is send as response to the users, and user store the token in client side, so client do further HTTP call using this token which can be added to the header and server validates the token and send a response. This article will give you a step by step process to implement the token-based authentication in ASP.NET Web API 2.

Implementation of Token Based Authentication

Step 1

Open visual studio 2017 => create a new Web API project => Name the project, in my case, I named it as Token_Auth_Web_API, set the Authentication to Individual User Account as shown in below figure.



Step 2

Go to Startup.cs file under App_Start folder in the solution
  1. // Configure the application for OAuth based flow
  2. PublicClientId = "self";
  3. OAuthOptions = new OAuthAuthorizationServerOptions
  4. {
  5. TokenEndpointPath = new PathString("/Token"),
  6. Provider = new ApplicationOAuthProvider(PublicClientId),
  7. AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
  8. AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
  9. // In production mode set AllowInsecureHttp = false
  10. AllowInsecureHttp = true
  11. };
Install the Owin using the below command in package manager console
  1. Install-Package Owin -Version 1.0.0
Owin :open web interface for .NET is a middleware which defines the interface between the web server and application.
TokenEndPointPath : This is a kind of request path client applications which communicate with server directly as part of the OAuth protocol. It must begin with slash “/”
  1. Provider : The object provided by the application to process the event raised by the authorization server middleware.
  2. AuthorizeEndpointPath : The request path where the client application will redirect the client/user to obtain user account to issue a token
  3. AccessTokenExpireTimeSpan : Defines the validity of token
  4. AllowInsecureHttp : It will allow a normal http request to authorize, if it is set to false, it will process only https request.

Step 3

To register the user, we are going to using api/Account/Register End point from client which is available in AccountController of our WEB API project, as shown below.
  1. // POST api/Account/Register
  2. [AllowAnonymous]
  3. public async Task<IHttpActionResult> Register(RegisterBindingModel model)
  4. {
  5. if (!ModelState.IsValid)
  6. {
  7. return BadRequest(ModelState);
  8. }
  9.  
  10. var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };
  11.  
  12. IdentityResult result = await UserManager.CreateAsync(user, model.Password);
  13.  
  14. if (!result.Succeeded)
  15. {
  16. return GetErrorResult(result);
  17. }
  18.  
  19. return Ok();
  20. }
Go to the Index View of the home controller, as shown in below figure and add the below code
Home=> Index.cshtml
  1. <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
  2. <h4> Registration Form</h4>
  3. <div id="loginDiv" style="width:50%">
  4. <div style="width:50%">
  5. <div class="form-group">
  6. <label for="txtEmail">First Name </label>
  7. <input type='email' name="email" id="txtEmail" class="form-control">
  8. </div>
  9. <div class="form-group">
  10. <label>Password</label>
  11. <input type="password" id="textPwd" class="form-control">
  12. </div>
  13. <div class="form-group">
  14. <label>Confrim Password</label>
  15. <input type="password" id="txtConfirmPwd" class="form-control">
  16. </div>
  17. </div>
  18. <button id="register" class="btn btn-default">Submit</button>
  19. </div>
  20. <h4>Login </h4>
  21. <div id="loginDiv" style="width:50%">
  22. <div class="form-group">
  23. <label for="txtEmail">First Name </label>
  24. <input type='email' name="email" id="loginEmail" class="form-control">
  25. </div>
  26. <div class="form-group">
  27. <label>Password</label>
  28. <input type="password" id="loginPwd" class="form-control">
  29. </div>
  30. <button id="btnLogin" class="btn btn-default">Submit</button>
  31. </div>
  32. <div>
  33. <label id="msg"></label>
  34. </div>
  35. <script>
  36. $(document).ready(function () {
  37. $("#register").on('click', function () {
  38. var data = { Email: $("#txtEmail").val().trim(), Password: $("#textPwd").val().trim(), ConfirmPassword: $("#txtConfirmPwd").val().trim() };
  39. $.ajax({
  40. url: "http://localhost:49501/api/Account/Register",
  41. type: 'POST',
  42. data: data,
  43. success: function (resp) {
  44. window.location.href = '/Home/Index';
  45. }
  46. })
  47. });
  48. $("#btnLogin").on('click', function () {
  49. //var data = { Email: $("#loginEmail").val().trim(), Password: $("#textPwd").val().trim(), ConfirmPassword: $("#loginPwd").val().trim() };
  50. $.ajax(
  51. {
  52. url: "/TOKEN",
  53. type: "POST",
  54. data: $.param({ grant_type: 'password', username: $("#loginEmail").val(), password: $("#loginPwd").val() }),
  55. headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  56. success: function (resp) {
  57. sessionStorage.setItem('userName', resp.userName);
  58. sessionStorage.setItem('accessToken', resp.access_token);
  59. var authHeaders = {};
  60. authHeaders.Authorization = 'Bearer ' + resp.access_token;
  61. $.ajax({
  62. url: "http://localhost:49501/api/values",
  63. type: "GET",
  64. headers: authHeaders,
  65. success: function (response) {
  66. $("#loginEmail").val("");
  67. $("#loginPwd").val("");
  68. $("#msg").text(response);
  69. }
  70. });
  71. },
  72. error: function () {
  73. $("#msg").text("Authentication failed");
  74. }
  75. })
  76. });
  77. })
  78. </script>
From the above HTML code, it is obvious we have two form
  • Registration Form
  • Login Form
Registration Form : Registration Form is used to register the user using the /api/Account/Register API Service which doesn’t require any authentication
Login Form : In this user request to give their credential, once they submit the form /TOKEN post service is fired, once the service validates the user it will generate a access token and send it is as response to server with username as shown in below figure.



In Login Ajax call success, we are saving the token and user details, and making another API call /api/values, this function definition is decorated with [authorize] attribute. we need to pass the access token as an authorization header whenever this HTTP service request happens from the client side.
  1. // GET api/values
  2. [EnableCors(origins: "*", headers: "*", methods: "*", exposedHeaders: "X-My-Header")]
  3. [Authorize]
  4. public IEnumerable<string> Get()
  5. {
  6. return new string[] {"You are successfully Authenticated to Access the Service"};
  7. }
[EnableCors(origins: "*", headers: "*", methods: "*", exposedHeaders: "X-My-Header")] : Enabled the CROS origin, so that it can be accessed from any domain
[Authorize] : It is used to authenticate the token send from the client side, once the authentication is successfully the Get() will be fired

Client-side HTTP request with Authorization Header

  1. $("#btnLogin").on('click', function () {
  2. $.ajax(
  3. {
  4. url: "/TOKEN",
  5. type: "POST",
  6. data: $.param({ grant_type: 'password', username: $("#loginEmail").val(), password: $("#loginPwd").val() }),
  7. headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  8. success: function (resp) {
  9. sessionStorage.setItem('userName', resp.userName);
  10. sessionStorage.setItem('accessToken', resp.access_token);
  11. var authHeaders = {};
  12. authHeaders.Authorization = 'Bearer ' + resp.access_token;
  13. $.ajax({
  14. url: "http://localhost:49501/api/values",
  15. type: "GET",
  16. headers: authHeaders,
  17. success: function (response) {
  18. $("#loginEmail").val("");
  19. $("#loginPwd").val("");
  20. $("#msg").text(response);
  21. }
  22. });
  23.  
  24. },
  25. error: function () {
  26. $("#msg").text("Authentication failed");
  27. }
  28. })
authHeaders.Authorization = 'Bearer ' + resp.access_token : We are defining the authorization header with the access token when the /api/values HTTP call happens. In server side the token is validated, once its success it will return a message “You are successfully Authenticated to Access the Service”
Note : we need to send grant_type: 'password' as the data along with user name and password through the body of HTTP request which accessing the URL /TOKEN




Header with /api/values HTTP call

 

 


Success

 


From the above figures it is obvious the token is validated, and the service returns a message.



Invalid Credential Entry

 


If the credential is wrong the service /TOKEN will return the error message which is shown above
Summary
From this article we have learned the complete process of token-based authentication in ASP.NET Web API 2, where we have seen how to generate the token by sending the user credential and how to use the token with HTTP header for further communication with server through HTTP request to access a secured API Service.