Securing ASP.NET Web API using basic Authentication

Basic HTTP Authentication

In basic HTTP authentication the client passes their username and password in the HTTP request header. Typically, using this technique we encrypt user credentials string into base64 encoded string and decrypt this base64 encoded string into plain text. You can also use another encryption and decryption technique.

Custom Principal

Since WebAPI is build on the top of ASP.NET Framework, hence it can use ASP.NET Framework features like ASP.NET membership and provider. ASP.NET provides IPrincipal and IIdentity interfaces to represents the identity and role for a user. For ASP.NET Web API, you can also create a custom solution by evaluating the IPrincipal and IIdentity interfaces which are bound to the HttpContext as well as the current thread.

  1. publicclassCustomPrincipal:IPrincipal
  2. {
  3. publicIIdentityIdentity{ get;privateset;}
  4. publicboolIsInRole(string role)
  5. {
  6. if(roles.Any(r => role.Contains(r)))
  7. {
  8. returntrue;
  9. }
  10. else
  11. {
  12. returnfalse;
  13. }
  14. }
  15.  
  16. publicCustomPrincipal(string Username)
  17. {
  18. this.Identity=newGenericIdentity(Username);
  19. }
  20.  
  21. publicintUserId{ get;set;}
  22. public string FirstName{ get;set;}
  23. public string LastName{ get;set;}
  24. public string[] roles { get;set;}
  25. }

Now you can put this CustomPrincipal objects into the thread’s currentPrinciple property and into the HttpContext’s User property to accomplish your custom authentication and authorization process.

Custom ASP.NET Web API Authorization Filter

Like ASP.NET MVC, Web API also provides Authorization filter to authorize a user. This filter can be applied to an action, a controller, or even globally. This filter is based on AuthorizeAttribute class exist in System.Web.Http namespace. You can customize this filter by overriding OnAuthorization() method as shown below:

  1. //custom authorize filter attribute
  2. publicclassCustomAuthorizeAttribute:AuthorizeAttribute
  3. {
  4. privateconst string BasicAuthResponseHeader=“WWW-Authenticate”;
  5. privateconst string BasicAuthResponseHeaderValue=“Basic”;
  6. readonly DataContextContext=newDataContext();
  7.  
  8. public string UsersConfigKey{ get;set;}
  9. public string RolesConfigKey{ get;set;}
  10.  
  11. protectedCustomPrincipalCurrentUser
  12. {
  13. get {returnThread.CurrentPrincipal as CustomPrincipal;}
  14. set{Thread.CurrentPrincipal= value as CustomPrincipal;}
  15. }
  16.  
  17. public override voidOnAuthorization(HttpActionContext actionContext)
  18. {
  19. try
  20. {
  21. AuthenticationHeaderValue authValue = actionContext.Request.Headers.Authorization;
  22.  
  23. if(authValue != null &&!String.IsNullOrWhiteSpace(authValue.Parameter)&& authValue.Scheme==BasicAuthResponseHeaderValue)
  24. {
  25. Credentials parsedCredentials =ParseAuthorizationHeader(authValue.Parameter);
  26.  
  27. if(parsedCredentials != null)
  28. {
  29. var user =Context.Users.Where(u => u.Username== parsedCredentials.Username&& u.Password== parsedCredentials.Password).FirstOrDefault();
  30. if(user != null)
  31. {
  32. var roles = user.Roles.Select(m => m.RoleName).ToArray();
  33. var authorizedUsers =ConfigurationManager.AppSettings[UsersConfigKey];
  34. var authorizedRoles =ConfigurationManager.AppSettings[RolesConfigKey];
  35.  
  36. Users=String.IsNullOrEmpty(Users)? authorizedUsers :Users;
  37. Roles=String.IsNullOrEmpty(Roles)? authorizedRoles :Roles;
  38.  
  39. CurrentUser=newCustomPrincipal(parsedCredentials.Username, roles);
  40.  
  41. if(!String.IsNullOrEmpty(Roles))
  42. {
  43. if(!CurrentUser.IsInRole(Roles))
  44. {
  45. actionContext.Response= actionContext.Request.CreateResponse(HttpStatusCode.Forbidden);
  46. actionContext.Response.Headers.Add(BasicAuthResponseHeader,BasicAuthResponseHeaderValue);
  47. return;
  48. }
  49. }
  50.  
  51. if(!String.IsNullOrEmpty(Users))
  52. {
  53. if(!Users.Contains(CurrentUser.UserId.ToString()))
  54. {
  55. actionContext.Response= actionContext.Request.CreateResponse(HttpStatusCode.Forbidden);
  56. actionContext.Response.Headers.Add(BasicAuthResponseHeader,BasicAuthResponseHeaderValue);
  57. return;
  58. }
  59. }
  60.  
  61. }
  62. }
  63. }
  64. }
  65. catch(Exception)
  66. {
  67. actionContext.Response= actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
  68. actionContext.Response.Headers.Add(BasicAuthResponseHeader,BasicAuthResponseHeaderValue);
  69. return;
  70.  
  71. }
  72. }
  73.  
  74. privateCredentialsParseAuthorizationHeader(string authHeader)
  75. {
  76. string[] credentials =Encoding.ASCII.GetString(Convert.FromBase64String(authHeader)).Split(new[]{‘:’});
  77.  
  78. if(credentials.Length!=2|| string.IsNullOrEmpty(credentials[0])|| string.IsNullOrEmpty(credentials[1]))
  79. return null;
  80.  
  81. returnnewCredentials(){Username= credentials[0],Password= credentials[1],};
  82. }
  83. }
  84. //Client credential
  85. publicclassCredentials
  86. {
  87. public string Username{ get;set;}
  88. public string Password{ get;set;}
  89. }

Applying CustomAuthorize attribute

To make secure your service, decorate your Web API controllers with CustomAuthorize attribute as defined above and specify the uses or roles to access specific service actions/methods. The below product service action Getproduct can be access only by Admin users.

  1. publicclassProductController:ApiController
  2. {
  3. [CustomAuthorize(Roles=“Admin”)]
  4. publicHttpResponseMessageGetproducts()
  5. {
  6. var products =newProduct[]
  7. {
  8. newProduct()
  9. {
  10. Id=1,
  11. Name=“Soap”,
  12. Price=25.12
  13. },
  14. newProduct()
  15. {
  16. Id=2,
  17. Name=“Shampoo”,
  18. Price=25.12
  19. }
  20. };
  21.  
  22. var response =Request.CreateResponse<ienumerable>(HttpStatusCode.OK, products);
  23. <ienumerablereturn response;
  24. <ienumerable}
  25. <ienumerable}

Calling Web API and passing client credential from ASP.NET MVC

  1. publicclassHomeController:Controller
  2. {
  3. //
  4. // GET: /Home/
  5. publicActionResultIndex()
  6. {
  7. string FullName=User.FirstName+” “+User.LastName;
  8. HttpClient client =newHttpClient();
  9. string authInfo =“admin”+“:”+“123456”;
  10. authInfo =Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
  11. client.DefaultRequestHeaders.Authorization=newAuthenticationHeaderValue(“Basic”, authInfo);
  12.  
  13. client.BaseAddress=newUri(http://localhost:63173/&#8221;);
  14.  
  15. HttpResponseMessage response = client.GetAsync(“api/product/”).Result;
  16. if(response.IsSuccessStatusCode)
  17. {
  18. // Parse the response body. Blocking!
  19. var data = response.Content.ReadAsAsync<ienumerable>().Result;
  20. <ienumerablereturnView();
  21. <ienumerable}
  22. <ienumerablereturnView();
  23. <ienumerable}
  24. <ienumerable}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

%d bloggers like this: