Monday, June 18, 2012

MVC-Authentication-Authorization




MVC authentication and authorization, custom Filters  example

Login Class

public class UserLogon
{
    [Required]
    [Display(Name = "User Login")]
    public string UserName { get; set; }

    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

}


Account Controller 

using System;
using System.Web;
using System.Collections.Generic;
using System.Linq;
using System.Web.Security;
using System.Web.Mvc;


namespace MvcTextApplication.Controllers
{
    public class AccountController : Controller
    {
        public ActionResult LogOn()
        {
            return View();
        }

        //
        // POST: /Account/LogOn

        [HttpPost]
        public ActionResult LogOn(UserLogon model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
              
                 string Role = "";

                // Passw0rd can be get from database
                // I am assigning one common password
                 string password = "common";

                // Role can be get from database also
                // I am assigning roles manually
                if (model.UserName == "adminuser")
                {
                    Role = "Admin";

                }
                else if (model.UserName == "staffuser")
                {
                    Role = "SU";
                }
                else
                {
                    Role = "Others";
                }

                if (string.IsNullOrEmpty(model.UserName) || string.IsNullOrEmpty(model.Password))
                {
                    ModelState.AddModelError("", "The user login or password provided is incorrect.");
                }

                // we are checking here if Passowrd entered by user is same as our password eg: common
                if (model.Password == password)
                {

                    // create FormsAuthenticationTicket
                            var authTicket = new FormsAuthenticationTicket(
                                            1,                             // version
                                            model.UserName,                 // user name
                                            DateTime.Now,                  // created
                                            DateTime.Now.AddMinutes(20),   // expires
                                            false,                         // persistent?
                                            Role.ToString()               // can be used to store roles
                                            );

                    string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
                    var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
                    System.Web.HttpContext.Current.Response.Cookies.Add(authCookie);

                    if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                        && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
                    {                      
                        return Redirect(returnUrl);
                    }
                    else
                    {
                        
                        return RedirectToAction("../Security/Index");
                      
                    }
                }
                else
                {
                    ModelState.AddModelError("", "The password provided is incorrect.");
                }
            }

          
            return View(model);
        }


        public ActionResult LogOff()
        {
            FormsAuthentication.SignOut();

            return RedirectToAction("Index", "Home");
        }
    }
}


Login View

<h2>LogOn</h2>

<script src="<%: Url.Content("~/Scripts/jquery.validate.min.js") %>" type="text/javascript"></script>
<script src="<%: Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js") %>" type="text/javascript"></script>

<% using (Html.BeginForm()) { %>
    <%: Html.ValidationSummary(true) %>
    <fieldset>
        <legend>UserLogon</legend>

        <div class="editor-label">
            <%: Html.LabelFor(model => model.UserName) %>
        </div>
        <div class="editor-field">
            <%: Html.EditorFor(model => model.UserName) %>
            <%: Html.ValidationMessageFor(model => model.UserName) %>
        </div>

        <div class="editor-label">
            <%: Html.LabelFor(model => model.Password) %>
        </div>
        <div class="editor-field">
            <%: Html.EditorFor(model => model.Password) %>
            <%: Html.ValidationMessageFor(model => model.Password) %>
        </div>

        <p>
            <input type="submit" value="Login" />
        </p>
    </fieldset>
<% } %>

<div>
    <%: Html.ActionLink("Back to List", "Index") %>
</div>






We can see in Controller class that if user Login adminuser then role  would be Admin and if user Login is  staffuser then role would be SU other role would be Others 






Custom Error View :
 
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/MasterPage.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">

<h2>Custom Error Page </h2> <br /><br />

 <%= (string)ViewBag.ErrorMessage %>

</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
</asp:Content>

<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder2" runat="server">
</asp:Content>

 








Security Controller class:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcTextApplication.Controllers
{
    [HandleError]
    public class SecurityController : Controller
    {
        //Can be accessed by anonymous users    
        public ActionResult Index()
        {
            ViewData["Message"] = "Welcome to My website";
            return View();
        }

       [CustomAuthorizeSecod]
        public ActionResult About()
        {
            ViewData["Message"] = "Welcome to My website About Page";
            return View();
        }

        
        [Authorize]   
        public ActionResult AuthenticatedUsers()
        {
            ViewData["Message"] = "Welcome to My website Authenticated Users Page";
            return View();
        }

        [Authorize(Users = "staffuser")]
        public ActionResult Users()
        {
            ViewData["Message"] = "Welcome to My website Authenticated Specific users";
            return View();
        }


       
        [Authorize(Roles = "Admin,SU")]     
        public ActionResult Roles()
        {
            ViewData["Message"] = "Welcome to My website Authenticated Users admin adn SU Page";
            return View();
        }


    }
}



CustomAuthorizeSecod  Class :





using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;


    public class CustomAuthorizeSecod : FilterAttribute, IAuthorizationFilter
    {

        public void OnAuthorization(AuthorizationContext filterContext)
        {

         
                var Controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
                var Action = filterContext.ActionDescriptor.ActionName;
                var User = filterContext.HttpContext.User;
                var IP = filterContext.HttpContext.Request.UserHostAddress;
              

                if (filterContext.HttpContext.Request.IsAuthenticated)
                {

                    if (filterContext.HttpContext.User.IsInRole("Admin"))
                    {
                        return;      
                    }
                    else
                    {

                           ViewResult result = new ViewResult();
                            result.ViewName = "../Error/CustomError";
                            result.ViewBag.ErrorMessage = "You are not authenticated. Please log-in and try again!";
                            filterContext.Result = result;
                       // }
                    }
                }
                else
                {

                    ViewResult result = new ViewResult();
                    result.ViewName = "../Error/CustomError";
                    result.ViewBag.ErrorMessage = "You are not authenticated. Please log-in and try again!";
                    filterContext.Result = result;
                }         

        }

    }




Important Steps:

Webconfig File :  Add  following code

    <authentication mode="Forms">
      <forms loginUrl="~/Account/Logon" timeout="2880" />
    </authentication>
   

Global File : Add following code
  protected void Application_AuthenticateRequest(Object sender, EventArgs e)
        {
            HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
            if (authCookie == null || authCookie.Value == "")
                return;

            FormsAuthenticationTicket authTicket;
            try
            {
                authTicket = FormsAuthentication.Decrypt(authCookie.Value);
            }
            catch
            {
                return;
            }

            // retrieve roles from UserData
            string[] roles = authTicket.UserData.Split(';');

            if (Context.User != null)
                Context.User = new GenericPrincipal(Context.User.Identity, roles);
        }



Login as AdminUser 
 Role =Admin





Redirected to following screen 


 Type following URL



  Which will call Following method


        [Authorize(Users = "staffuser")]
        public ActionResult Users()
        {
            ViewData["Message"] = "Welcome to My website Authenticated Specific users";
            return View();
        }

Only  staffuser can access this Action method so browser redirect to Logon view
which we specify in WEBCONFIG FILE









1 comment :