| by Achyut Kendre | No comments

Custom Authorization Filter in ASP.NET MVC 5

ASP NET MVC 5

Example Link: https://drive.google.com/file/d/1UXBYez5z8FlPPadz42oyoIrF-XIrfhWk/view?usp=sharing

In this article we will study how to create the custom authorize filter step by step.

Step1: Create tables

Please create the UserTbl and CustomerTbl as follows –

Step 2: Create a ASP.NET MVC Application using regular steps.

Step 2: Create a CustController with index action to display list of controller , this is the controller that we want to authorize using login.

namespace CustAuthFilterEx.Controllers
{
   
    public class CustController : Controller
    {
        // GET: Cust
        APIExampleEntities entity = new APIExampleEntities();
        public ActionResult Index()
        {
            return View(entity.CustomerTbls.ToList());
        }
    }
}

Step 3: Create a Entity Model using EntityFramework DbFirst Appraoch

Step 3: Implement Login and Registration Activities / Functionalities.

In this step create ManageUsers controller which will contain the dologin and doRegistration methods.

doLogin methods will have two versions [HttpGet] and [HttpPost] where Get will generate the LoginView and HttpPost will validate the user using email id and password and divert the user to specific controller and action as follows –

DoLogin Actions:

public class ManageUsersController : Controller
{
        APIExampleEntities entity = new APIExampleEntities();
        // GET: ManageUsers
        [HttpGet]
        public ActionResult doLogin()
        {
            return View();
        }

   [HttpPost]
    public ActionResult doLogin(LoginVM rec)
        {
            if (ModelState.IsValid)
            {
UserTbl urec = entity.UserTbls.SingleOrDefault(p => p.EmailID == rec.EmailID && p.Password == rec.Password);
                if (urec != null)
                {
         
                    Session["UserID"] = urec.UserID;
                    Session["UserName"] = urec.UserName;
                    return RedirectToAction("Index", "Cust");
                }
                else
                {
    ModelState.AddModelError("", "Invalid Email ID or Password!");
                    return View(rec);
                }
            }
            return View(rec);
        }
}

DoLogin.cshtml Code

@model CustAuthFilterEx.Models.LoginVM

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>doLogin</title>
</head>
<body>
    @using (Html.BeginForm()) 
    {
        @Html.AntiForgeryToken()
        
        <div class="form-horizontal">
            <h4> USer Login</h4>
            <hr />
            @Html.ValidationSummary(true, "", new { @class = "text-danger" })
            <div class="form-group">
                @Html.LabelFor(model => model.EmailID, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.EmailID, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.EmailID, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.Password, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Password, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="Login" class="btn btn-default" />
                    @Html.ActionLink("New User","signup") 
                </div>
            </div>
        </div>
    }
 
</body>
</html>

Now implement the Registration, to implement it we need to create doRegistration action with [HttpGet] and [HttpPost] actions where [HttpGet] decorated action will create the registration form and submit it to the doRegistration action decorated using [HttpPost] as follows –

[HttpGet]
public ActionResult doRegistration()
{
  return View();
 }

 [HttpPost]
 public ActionResult doRegistration(UserTbl rec)
  {
     if (ModelState.IsValid)
        {
           entity.UserTbls.Add(rec);
           entity.SaveChanges();
           return RedirectToAction("doLogin");
        }
      return View(rec);
  }

doRegistration.cshtml

@model CustAuthFilterEx.Models.UserTbl

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>SignUp</title>
</head>
<body>
 @using (Html.BeginForm()) 
 {
        @Html.AntiForgeryToken()
 <div class="form-horizontal">
      <h4>UserTbl</h4>
          <hr />
 @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
 @Html.LabelFor(model => model.UserName, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
 @Html.EditorFor(model => model.UserName, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.UserName, "", new { @class = "text-danger" })
            </div>
         </div>
 div class="form-group">
   @Html.LabelFor(model => model.EmailID, htmlAttributes: new { @class = "control-label col-md-2" })
             <div class="col-md-10">
          @Html.EditorFor(model => model.EmailID, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.EmailID, "", new { @class = "text-danger" })
         </div>
    </div>
        <div class="form-group">
   @Html.LabelFor(model => model.Password, htmlAttributes: new { @class = "control-label col-md-2" })
         <div class="col-md-10">
 @Html.EditorFor(model => model.Password, new { htmlAttributes = new { @class = "form-control" } })
  @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" })
                </div>
            </div>
    <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
    <input type="submit" value="Create" class="btn btn-default" />
                </div>
            </div>
        </div>
    }
       <div>
        @Html.ActionLink("Back to List", "Index")
    </div>
</body>
</html>

Now Authorize the CustController using the Custom Authorization filter

To create a custom authorize filter, define a class which inherits from AuthorizeAttribute class and AuthorizeAttribute class has a method OnAuthorization method override it and write a custom logic to check weather user is logged in or not.

For this we had already decided to use the Session mechanism , when user logged in it will create a userid variable in session and using that we can confirm that user id loggeed in , since the userid will be get created in session variable only when user is logged in and we will delete it or remove it when user will be logged in.

So we need to check weather userid exists in Session variable, if yes then user is logged in if not then we will divert the user to login action of the ManageUsers controller as follows –

namespace CustAuthFilterEx.CustAuth
{
 public class UserAuth :AuthorizeAttribute
 {
 public override void OnAuthorization(AuthorizationContext filterContext)
  {
    if (filterContext.HttpContext.Session["UserID"] == null)
      {
      filterContext.Result = new RedirectToRouteResult(new System.Web.Routing.RouteValueDictionary(new { action = "doLogin", controller = "ManageUsers" }));
       }
    }
  }
}

Now apply this Attribute on the controller that you want to authorize as follows –

namespace CustAuthFilterEx.Controllers
{
    [UserAuth]
    [OutputCache(Duration =0,NoStore =true,VaryByParam ="none")]
    public class CustController : Controller
    {
        // GET: Cust
        APIExampleEntities entity = new APIExampleEntities();
        public ActionResult Index()
        {
            return View(entity.CustomerTbls.ToList());
        }
    }
}

In above code we had also applied [OutputCache] directive to prevent to store the result of action in cache by any chance if the browser cache the output of the action.