Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Custom Authentication and Authorization in MVC 5

0.00/5 (No votes)
11 Jul 2016 5  
Here I explain how to create custom authentication and mapping it to the default filters like Authorize, roles..etc

Introduction

There are certain scenario's in our projects we which needs to used for custom Authentication instead of using Default MVC5 Asp.net Identity mechanism. So here I am explaining on how to create custom authentication and mapping it to the default filters like Authorize, roles..etc.

Steps to follow

  1. Open visual studio create a new project

2. Select ASP.NET Application and name the project

3. Select MVC template

4. After loading the project , create a new folder DAL (Here we can call our custom implementation methods for User Authentication)

5. Now project structure looks like the below diagram in solution explorer

6. Add two classes in DAL layer, User.cs and Repository.cs 

7. Paste the below code in User.cs file

public class User
{
    public string Email { get; set; }
    public string Roles { get; set; }
    public string Password { get; set; }
}

8. Paste the below code in Repository.cs file

public static class Repository
{
   static List<User> users = new List<User>() {

        new User() {Email="abc@gmail.com",Roles="Admin,Editor",Password="abcadmin" },
        new User() {Email="xyz@gmail.com",Roles="Editor",Password="xyzeditor" }
    };

    public static User GetUserDetails(User user)
    {
        return users.Where(u => u.Email.ToLower() == user.Email.ToLower() &&
        u.Password == user.Password).FirstOrDefault();
    }
}

9.  Open  “AccountController” in Controllers folder.

10.  Goto method called Login(LoginViewModel model, string returnUrl)

Delete the below code from the Login method

11. Paste the below code inside login method

if (!ModelState.IsValid)
{
    return View(model);
}

User user = new User() { Email=model.Email,Password=model.Password};

user = Repository.GetUserDetails(user);

if (user!=null)
{
    FormsAuthentication.SetAuthCookie(model.Email, false);

    var authTicket = new FormsAuthenticationTicket(1, user.Email, DateTime.Now, DateTime.Now.AddMinutes(20), false, user.Roles);
    string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
    var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
    HttpContext.Response.Cookies.Add(authCookie);
    return RedirectToAction("Index", "Home");
}

else
{
    ModelState.AddModelError("", "Invalid login attempt.");
    return View(model);
}
  1. Goto public ActionResult LogOff() method in AccountController itself

        Replace existing code with below code

//
// POST: /Account/LogOff
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
    //AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
    FormsAuthentication.SignOut();
    return RedirectToAction("Index", "Home");
}
  1. Open Global.asax.cs file

 Paste the below method

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
    var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
    if (authCookie != null)
    {
        FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
        if (authTicket != null && !authTicket.Expired)
        {
            var roles = authTicket.UserData.Split(',');
            HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(authTicket), roles);
        }
    }
}

Now the settings required for Authentication and roles have been completed.

Lets see what have we created and how are we going to use those

1.    We have created 2 users Admin,Editor in Repository.cs class

2.    Now In Home Controller “Index” method we will give access to only “Admin” ,for “About” method will give access to both “Admin and Editor”.

Decorate HomeController with [Authorize] attribute first to restrict unauthorized access, decorate remaining two methods with respective roles as discussed above.

See the below code snippet for reference

[Authorize]

public class HomeController : Controller
    [Authorize(Roles = "Admin")]
    public ActionResult Index()
    {
        return View();
    }

    [Authorize(Roles = "Admin,Editor")]
    public ActionResult About()
    {
        ViewBag.Message = "Your application description page.";

        return View();
    }

That’s it, our application is ready with custom authentication and authorization.

Now let’s run the application, as we have decorated HomeControllerwith [Authorize] attribute, we will get Login page first instead of Default HomeController Index method.

If we see the url it is not directly called Account/Login method, there is extra ReturnUrl

http://localhost:51581/Account/Login?ReturnUrl=%2F

See default route config as below

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

So when it goes to HomeController directly it doesn’t get authenticated so it redirects to Login page in AccountController. Now enter the required credentials created by us. I am entering admin details i.e.

Now when we click the Login Button, it will redirect to Index method in HomeController.

When we see extreme right corner , it will read the User details from context and Hello abc@gmail.com!

Now Logoff and enter editor credentials.

When we click on Login Page we will be same screen, but Right side we can see User is authenticated (Hello xyz@gmail.com!), because he doesn’t have permission to call Index method it will show the same page.

Now just Point the Url to HomeController, “About” method as below.

http://localhost:51581/Home/About

we will be redirected to desired page, since “Editor” role has permission he can access the About Action method.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here