• Home
  • About
  • Contact
  • ado.net
  • angular
  • c#.net
  • design patterns
  • linq
  • mvc
  • .net core
    • .Net Core MVC
    • Blazor Tutorials
  • sql
  • web api
  • dotnet
    • SOLID Principles
    • Entity Framework
    • C#.NET Programs and Algorithms
  • Others
    • C# Interview Questions
    • SQL Server Questions
    • ASP.NET Questions
    • MVC Questions
    • Web API Questions
    • .Net Core Questions
    • Data Structures and Algorithms

Monday, July 20, 2020

Role-Based Basic Authentication in Web API

 Admin     July 20, 2020     .Net, Asp.Net, C#, Web API     No comments   

In this article, I am going to discuss how to implement the Role-Based Basic Authentication in Web API Application. Please read our last article before proceeding to this article, where we discussed How to implement ASP.NET Web API Basic Authentication with an example. As part of this article, we are going to discuss the following pointers related to authentication and authorization.
  1. Why do we need Role-Based Authentication?
  2. How to Implement Role-Based Basic Authentication in Web API?
  3. Testing the Role-Based Basic Authentication using Postman.
  4. What are the advantages and disadvantages of using BASIC Authentication in Web API?
Why do we need Role-Based Authentication?
Let us understand this with an example. As shown in the above image, we have three resources i.e. GetAllMaleEmployees, GetAllFemaleEmployees, and GetAllEmployees in our service.
Role-Based Basic Authentication in Web API

In our application, we have two types of Roles i.e. Admin and Superadmin. As per our business requirement,
  1. Only the users who have the Role Admin can access only to the GetAllMaleEmployees resource.
  2. The users who have the Role Superadmin can access only to the GetAllFemaleEmployees resource.
  3. The GetAllEmployees resource can be accessed by both the Admin and Superadmin resource.
In order to achieve this, we need to implement Role-Based Authentication.

Implementing Role-Based Basic Authentication in Web API.
First, create an empty Web API application with the name RoleBasedBasicAuthenticationWEBAPI. The Add the following User and Employee model to the Models folder

User.cs
namespace RoleBasedBasicAuthenticationWEBAPI.Models
{
    public class User
    {
        public int ID { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
        public string Roles { get; set; }
        public string Email { get; set; }
    }
}
Employee.cs
namespace RoleBasedBasicAuthenticationWEBAPI.Models
{
    public class Employee
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Gender { get; set; }
        public string Dept { get; set; }
        public int Salary { get; set; }
    }
}
Now we need to add the UserBL and EmployeeBL class file within the Models folder.

UserBL.cs
namespace RoleBasedBasicAuthenticationWEBAPI.Models
{
    public class UsersBL
    {
        public List<user> GetUsers()
        {
            // In Realtime you need to get the data from any persistent storage
            // For Simplicity of this demo and to keep the focus on Basic Authentication
            // Here we are hardcoded the data
            List<User> userList = new List<User>();
            userList.Add(new User()
            {
                ID = 101,
                UserName = "AdminUser",
                Password = "123456",
                Roles = "Admin",
                Email = "Admin@a.com"
            });
            userList.Add(new User()
            {
                ID = 102,
                UserName = "BothUser",
                Password = "abcdef",
                Roles = "Admin,Superadmin",
                Email = "BothUser@a.com"
            });
            userList.Add(new User()
            {
                ID = 103,
                UserName = "SuperadminUser",
                Password = "Password@123",
                Roles = "Superadmin",
                Email = "Superadmin@a.com"
            });
            return userList;
        }
    }
}
EmployeeBL.cs
namespace RoleBasedBasicAuthenticationWEBAPI.Models
{
    public class EmployeeBL
    {
        public List<employee> GetEmployees()
        {
            // In Realtime you need to get the data from any persistent storage
            // For Simplicity of this demo and to keep the focus on Basic Authentication
            // Here we hardcoded the data
            List<Employee> empList = new List<Employee>();
            for (int i = 0; i < 10; i++)
            {
                if (i > 5)
                {
                    empList.Add(new Employee()
                    {
                        ID = i,
                        Name = "Name" + i,
                        Dept = "IT",
                        Salary = 1000 + i,
                        Gender = "Male"
                    });
                }
                else
                {
                    empList.Add(new Employee()
                    {
                        ID = i,
                        Name = "Name" + i,
                        Dept = "HR",
                        Salary = 1000 + i,
                        Gender = "Female"
                    });
                }
            }
            return empList;
        }
    }
}
Now add one more class file with the name UserValidate and copy and paste the following code.

UserValidate.cs
namespace RoleBasedBasicAuthenticationWEBAPI.Models
{
    public class UserValidate
    {
        //This method is used to check the user credentials
        public static bool Login(string username, string password)
        {
            UsersBL userBL = new UsersBL();
            var UserLists = userBL.GetUsers();
            return UserLists.Any(user =>
                user.UserName.Equals(username, StringComparison.OrdinalIgnoreCase)
                && user.Password == password);
        }
        //This method is used to return the User Details
        public static User GetUserDetails(string username, string password)
        {
            UsersBL userBL = new UsersBL();
            return userBL.GetUsers().FirstOrDefault(user =>
                user.UserName.Equals(username, StringComparison.OrdinalIgnoreCase)
                && user.Password == password);
        }
    }
}
Now create the BasicAuthenticationAttribute which will implement the AuthorizationFilterAttribute where we will put the logic for role-based basic authentication.

BasicAuthenticationAttribute.cs
namespace RoleBasedBasicAuthenticationWEBAPI.Models
{
    public class BasicAuthenticationAttribute : AuthorizationFilterAttribute
    {
        private const string Realm = "My Realm";
        public override void OnAuthorization(HttpActionContext actionContext)
        {
            if (actionContext.Request.Headers.Authorization == null)
            {
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
                if (actionContext.Response.StatusCode == HttpStatusCode.Unauthorized)
                {
                    actionContext.Response.Headers.Add("WWW-Authenticate", string.Format("Basic realm=\"{0}\"", Realm));
                }
            }
            else
            {
                string authenticationToken = actionContext.Request.Headers.Authorization.Parameter;
                string decodedAuthenticationToken = Encoding.UTF8.GetString(Convert.FromBase64String(authenticationToken));               
                string[] usernamePasswordArray = decodedAuthenticationToken.Split(':');
                string username = usernamePasswordArray[0];
                string password = usernamePasswordArray[1];
                if (UserValidate.Login(username, password))
                {
                    var UserDetails = UserValidate.GetUserDetails(username, password);
                    var identity = new GenericIdentity(username);
                    identity.AddClaim(new Claim("Email", UserDetails.Email));
                    identity.AddClaim(new Claim(ClaimTypes.Name, UserDetails.UserName));
                    identity.AddClaim(new Claim("ID", Convert.ToString(UserDetails.ID)));
                    IPrincipal principal = new GenericPrincipal(identity, UserDetails.Roles.Split(','));
                    Thread.CurrentPrincipal = principal;
                    if (HttpContext.Current != null)
                    {
                        HttpContext.Current.User = principal;
                    }
                }
                else
                {
                    actionContext.Response = actionContext.Request
                        .CreateResponse(HttpStatusCode.Unauthorized);
                }
            }
        }
    }
}
Please add the following namespaces.
using System;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
Now we will create out custom Authorize Attribute which will inherit from AuthorizeAttribute where we will implement the logic to return an appropriate response when the Authorization failed.

MyAuthorizeAttribute.cs
namespace RoleBasedBasicAuthenticationWEBAPI.Models
{
    public class MyAuthorizeAttribute : System.Web.Http.AuthorizeAttribute
    {
        // 401 (Unauthorized) - indicates that the request has not been applied because it lacks valid 
        // authentication credentials for the target resource.
        // 403 (Forbidden) - when the user is authenticated but isn’t authorized to perform the requested 
        // operation on the given resource.
        protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            if (!HttpContext.Current.User.Identity.IsAuthenticated)
            {
                base.HandleUnauthorizedRequest(actionContext);
            }
            else
            {
                actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Forbidden);
            }
        }
    }
}
Let’s create a Web API 2 Empty Controller with the name EmployeeController and copy and paste the following code.
using RoleBasedBasicAuthenticationWEBAPI.Models;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Web.Http;
namespace RoleBasedBasicAuthenticationWEBAPI.Controllers
{
    public class EmployeeController : ApiController
    {
        [BasicAuthentication]
        [MyAuthorize(Roles = "Admin")]
        [Route("api/AllMaleEmployees")]
        public HttpResponseMessage GetAllMaleEmployees()
        {
            var identity = (ClaimsIdentity)User.Identity;
            //Getting the ID value
            var ID = identity.Claims
                       .FirstOrDefault(c => c.Type == "ID").Value;
            //Getting the Email value
            var Email = identity.Claims
                      .FirstOrDefault(c => c.Type == "Email").Value;
            //Getting the Username value
            var username = identity.Name;
            //Getting the Roles only if you set the roles in the claims
            //var Roles = identity.Claims
            //            .Where(c => c.Type == ClaimTypes.Role)
            //            .Select(c => c.Value).ToArray();
            var EmpList = new EmployeeBL().GetEmployees().Where(e => e.Gender.ToLower() == "male").ToList();
            return Request.CreateResponse(HttpStatusCode.OK, EmpList);
        }
        [BasicAuthentication]
        [MyAuthorize(Roles = "Superadmin")]
        [Route("api/AllFemaleEmployees")]
        public HttpResponseMessage GetAllFemaleEmployees()
        {
            var EmpList = new EmployeeBL().GetEmployees().Where(e => e.Gender.ToLower() == "female").ToList();
            return Request.CreateResponse(HttpStatusCode.OK, EmpList);
        }
        [BasicAuthentication]
        [MyAuthorize(Roles = "Admin,Superadmin")]
        [Route("api/AllEmployees")]
        public HttpResponseMessage GetAllEmployees()
        {
            var EmpList = new EmployeeBL().GetEmployees();
            return Request.CreateResponse(HttpStatusCode.OK, EmpList);
        }
    }
}
That’s it. We have done with our implementation.

Testing Role-Based Basic Authentication in Web API using Postman
If you are new to the postman, I strongly recommended you read the following article, where I discussed how to download and use postman to test rest services.

https://csharptechtics.blogspot.com/2020/04/how-to-use-postman-to-test-web-api.html

We need to pass the username and password in the Authorization header. The username and password need to be a colon (:) separated and must be in base64 encoded. To do so, just use the following website

https://www.base64encode.org/

Enter the username and password separated by a colon (:) in “Encode to Base64 format” textbox, and then click on the “Encode” button as shown in the below diagram which will generate the Base64 encoded value. Let first generate the Base64 encoded string for the user AdminUser as shown in the below image
Testing Role-Based Basic Authentication in Web API using Postman

Once you generated the Base64 encoded string, let’s see how to use basic authentication in the header to pass the Base64 encoded value. Here we need to use the Authorization header and the value will be the Base64 encoded string followed the “BASIC” as shown below.

Authorization: BASIC TWFsZVVzZXI6MTIzNDU2

The role Admin has been assigned to the AdminUser. So he can access only the following two resources

/api/AllMaleEmployees /api/AllEmployees

But he cannot access the following resource

/api/AllFemaleEmployees

Let proofs this using the Postman.

/api/AllMaleEmployees
Role-Based Web API Authentication

Here we got the response 200 OK.

/api/AllEmployees
Role-Based Web API Authentication

Here we also got the response 200 OK as expected.

/api/AllFemaleEmployees
Role-Based Basic Authentication in WEB API

As you can see, here we got the response as 403 Forbidden which means the user is authenticated but not authorized to access the above resource. Similarly, you can test the other users.

Advantages and disadvantages of Basic Authentication in Web API.
Advantages:
  1. Internet standard.
  2. Supported by all major browsers.
  3. Relatively simple protocol.
Disadvantages:
  1. User credentials are sent in the request.
  2. Credentials are sent as plaintext.
  3. Credentials are sent with every request.
  4. No way to log out, except by ending the browser session.
  5. Vulnerable to cross-site request forgery (CSRF); requires anti-CSRF measures.
In the next article, I am going to discuss how to consume the Web API from JavaScript and C# client. Here, in this article, I try to explain the Role-Based Basic Authentication in Web API Application step by step with an example. I hope now you understood the need and use Role-Based Authentication in Web API.

Summary:
I hope this post will be helpful to understand the concept of Role-Based Basic Authentication in Web API
Please share this post with your friends and colleagues.
For any queries please post a comment below.
Happy Coding 😉
  • Share This:  
  •  Facebook
  •  Twitter
  •  Google+
  •  Stumble
  •  Digg
Newer Post Older Post

0 comments:

Post a Comment

If you like this website, please share with your friends on Facebook, Twitter, LinkedIn.

Join us on Telegram

Loved Our Blog Posts? Subscribe To Get Updates Directly To Your Inbox

Like us on Facebook

Popular Posts

  • What is Dependency Injection(DI)
    Hi friends! Today we are going to learn about Dependency Injection and in our last session we have come across Static classes and where it s...
  • C# Programming Examples on Sorting
    Today i am going to tell you some of the Sorting programming questions in C#. Q1- Write a C# program to perform Selection sort. Ans:  Sel...
  • Calling Web API Service in a Cross-Domain Using jQuery AJAX
    In this article, I am going to discuss Calling Web API Service in a Cross-Domain Using jQuery AJAX . Please read our previous article befor...
  • ViewBag in ASP.NET Core MVC
    In this article, I am going to discuss the use of ViewBag in ASP.NET Core MVC application with examples. Please read our previous article ...
  • Recursion And Back Tracking
    In this article, I am going to discuss Recursion And BackTracking in detail. Please read our previous article where we discussed Master Th...
  • What is Abstract Class and When we should use Abstract Class
    Hi friends! In our previous sessions we have seen  Difference Between Class and Struct . And in our last session  we learnt Usability of Sec...
  • Binary to Decimal Conversion in C# with Examples
    In this article, I am going to discuss the Binary to Decimal Conversion in C# with some examples. Please read our previous article where w...

Blog Archive

Contact Form

Name

Email *

Message *

Tags

.Net .Net Core .Net Core MVC Algorithm Angular Anonymous Types Asp.Net Asp.Net MVC Blazor C# Data Structure Database Design Patterns Entity Framework Entity Framework Core Filters Interview Question Management Studio Programming Programs SQL Server SSMS Web API

Copyright © C# Techtics | All Right Reserved.

Protected by Copyscape