Implementing Identity on ASP.NET MVC

buraknalpara.com

How to implement Identity on MVC ?

Implementing identity to your website is easy but a little bit confusing process at first. However when you get used to do this you will see that how easy to apply authentication and authorization on your MVC web applications or projects.

What we need to add as a reference for Identity?

We are going to use Entity Framework in our sample application that’s why we should install Entity Framework from NuGet Package Manager first of all. After that, let’s write “Identity” to the search console of the NuGet Package Manager and install the following packages:

  • Microsoft.AspNet.Identity.Core
  • Microsoft.AspNet.Identity.EntityFramework
  • Microsoft.AspNet.Identity.Owin

Then type “Owin” to search console

  • Microsoft.Owin
  • Microsoft.Owin.Host.SystemWeb

Please make sure that all the above references are installed correctly or you already have it. Now we can start writing our codes.

Add Identity to the project

Go to our solution and right click on it and click add New Folder. Name your folder as Identity. Right click on Identity folder and and some classes in it. First, add a class which name is “ApplicationRole.cs” for our Roles(You can name it whatever you want), secondly, create another class which name is “ApplicationUser.cs”, then create another class and name it “IdentityDataContext” and last but not least but it is optional of course, create a class for “IdentityInitializer.cs”.

Here is the code for ApplicationRole.cs:

using Microsoft.AspNet.Identity.EntityFramework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ReleaseManager.Identity
{
    public class ApplicationRole:IdentityRole
    {
        public string Description { get; set; }
    }
}

Our class is inherited from IdentityRole class which already contains names, Id, Users. We have just added description as an extra field for now, you can add more if you want.

Below you can see code for  ApplicationUser.cs:

using Microsoft.AspNet.Identity.EntityFramework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ReleaseManager.Identity
{
    public class ApplicationUser:IdentityUser
    {
        public string Name { get; set; }
        public string Surname { get; set; }
        public string Fathername { get; set; }
        public string MotherName { get; set; }
    }
}

I have added Name, Surname, FatherName, MotherName, but again you don’t have to add those or you can add more.

Here is the code for IdentityInitializer.cs:

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;

namespace ReleaseManager.Identity
{
    public class IdentityInitializer:CreateDatabaseIfNotExists<IdentityDataContext>
    {
        protected override void Seed(IdentityDataContext context)
        {
            if (!context.Roles.Any(i => i.Name == "Admin"))
            {
                var store = new RoleStore<ApplicationRole>(context);
                var manager = new RoleManager<ApplicationRole>(store);
                var role = new ApplicationRole() { Name = "Admin", Description = "Admin role" };
                manager.Create(role);
            }

            if (!context.Roles.Any(i => i.Name == "User"))
            {
                var store = new RoleStore<ApplicationRole>(context);
                var manager = new RoleManager<ApplicationRole>(store);
                var role = new ApplicationRole() { Name = "User", Description = "Standard User role" };
                manager.Create(role);
            }

            if (!context.Users.Any(i => i.Name == "buraknalpara"))
            {
                var store = new UserStore<ApplicationUser>(context);
                var manager = new UserManager<ApplicationUser>(store);
                var user = new ApplicationUser() { Name = "burak", Surname = "nalpara", UserName = "buraknalpara", Email = "buraknalpara@buraknalpara.com" };

                manager.Create(user, "123123");
                manager.AddToRole(user.Id, "Admin");
                manager.AddToRole(user.Id, "User");
            }

            if (!context.Users.Any(i => i.Name == "buraknalpara2"))
            {
                var store = new UserStore<ApplicationUser>(context);
                var manager = new UserManager<ApplicationUser>(store);
                var user = new ApplicationUser() { Name = "burak2", Surname = "nalpara2", UserName = "buraknalpara2", Email = "buraknalpara2@buraknalpara.com" };

                manager.Create(user, "123123");
                manager.AddToRole(user.Id, "User");
            }

            base.Seed(context);
        }
    }
}

What this initializer do is when you run the application we want to create some roles and users automatically. What i have done here is, I have created 2 roles one is Admin and the other one is User roles. I have also created 2 users one has admin role and the other one has user role.

And here is the code for our latest class inside Identity, IdentityDataContext.cs

using Microsoft.AspNet.Identity.EntityFramework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;

namespace ReleaseManager.Identity
{
    public class IdentityDataContext:IdentityDbContext<ApplicationUser>
    {
        public IdentityDataContext() : base("releaseConnection")
        {
            Database.SetInitializer(new IdentityInitializer());
        }

    }
}

In this piece of code, we need to inherit our context from IdentityDbContext and we need to pass our User class which is ApplicationUser for us. Also we wanted to Initialize our database at first run that’s why I have added Database.SetInitializer(new IdentityInitializer()); .

No we need to add Owin Startup class under App_Start folder. Right click on App_Start folder and click Add>Class. Under web section choose Owin Statup class and click Add.

Here you can see the code for Startup1.cs:

using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(ReleaseManager.App_Start.Startup1))]

namespace ReleaseManager.App_Start
{
    public class Startup1
    {
        public void Configuration(IAppBuilder app)
        {
            // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888
            app.UseCookieAuthentication(new Microsoft.Owin.Security.Cookies.CookieAuthenticationOptions()
            {
                AuthenticationType = "ApplicationCookie",
                LoginPath = new PathString("/Account/Login")
            });

        }
    }
}

Creating Account Controller on MVC

Right click on Controllers folder and Add > Controller. Name the controller as AccountController which is meaningful. We need to define user manager and role manager, see below to learn how to do it.

private UserManager<ApplicationUser> UserManager;
private RoleManager<ApplicationRole> RoleManager;

Now we need to create UserManager and RoleManager under constructor.

public AccountController()
        {
            UserStore<ApplicationUser> userStore =
                new UserStore<ApplicationUser>(new IdentityDataContext());
            UserManager = new UserManager<ApplicationUser>(userStore);

            var roleStore = new RoleStore<ApplicationRole>(new IdentityDataContext());
            RoleManager = new RoleManager<ApplicationRole>(roleStore);
        }

In the constructor we need to define UserStore and RoleStore and add them to our User Manager and Role Manager.

Here is the code for Register process under AccountController:

public ActionResult Register()
        {
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Register(Register model)
        {
            if (ModelState.IsValid)
            {
                
                var user = new ApplicationUser();
                user.Name = model.Name;
                user.Surname = model.Surname;
                user.Email = model.Email;
                user.UserName = model.Username;

                IdentityResult result = UserManager.Create(user, model.Password);
                if (result.Succeeded)
                {
                    if (RoleManager.RoleExists("User"))
                    {
                        UserManager.AddToRole(user.Id, "User");
                    }
                    return RedirectToAction("Login", "Account");
                }
                else
                {
                    ModelState.AddModelError("usercreateerror", "User could not be created");
                }

            }
            return View();
        }

Above code is creating a user under “User” role and if user is being created successfully system should redirect user to Login view. The view for Register.cshtml codes are shown below:

@model ReleaseManager.Models.Register
@{
    ViewBag.Title = "Register";
}
<h2>Register</h2>
<hr />
@Html.ValidationSummary()
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    <div class="form-group">
        <label>Username</label>
        @Html.TextBoxFor(model => model.Username, new { @class = "form-control" })
    </div>

    <div class="form-group">
        <label>Name</label>
        @Html.TextBoxFor(model => model.Name, new { @class = "form-control" })
    </div>

    <div class="form-group">
        <label>Surname</label>
        @Html.TextBoxFor(model => model.Surname, new { @class = "form-control" })
    </div>

    <div class="form-group">
        <label>Email</label>
        @Html.TextBoxFor(model => model.Email, new { @class = "form-control" })
    </div>

    <div class="form-group">
        <label>Password</label>
        @Html.PasswordFor(model => model.Password, new { @class = "form-control", @placeholder = "Password" })
    </div>

    <button type="submit" class="btn btn-primary">
        Register plsss
    </button>
}

This view needs Register model as you can see on the code so we need this Register class under Models folder in our application.

Here is the code for Register.cs

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

namespace ReleaseManager.Models
{
    public class Register
    {
        [Required]
        [DisplayName("Your Name")]
        public string Name { get; set; }
        [Required]
        [DisplayName("Your Surname")]
        public string Surname { get; set; }
        [Required]
        [DisplayName("Username")]
        public string Username { get; set; }
        public string Email { get; set; }
        [Required]
        [DisplayName("Password")]
        public string Password { get; set; }

    }
}

For Login Operations we need to write our codes for login processes.

Here is the code for login action.

public ActionResult Login()
        {
            return View();
        }

[HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Login(Login model, string ReturnUrl)
        {
            if (ModelState.IsValid)
            {
                var user = UserManager.Find(model.Username, model.Password);
                if (user != null)
                {
                    var authManager = HttpContext.GetOwinContext().Authentication;

                    var identityclaims = UserManager.CreateIdentity(user, "ApplicationCookie");
                    var authProperties = new AuthenticationProperties
                    {
                        IsPersistent = model.RememberMe
                    };

                    authManager.SignIn(authProperties, identityclaims);

                    if (!String.IsNullOrEmpty(ReturnUrl))
                    {
                        return Redirect(ReturnUrl);
                    }

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

                ModelState.AddModelError("LoginUserError", "Login failed");

            }

            return View();

        }

Here is the code for Login.cshtml.

@model ReleaseManager.Models.Login

@{
    Layout = null;
}

<!DOCTYPE html>
<html lang="en">

<head>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>SB Admin 2 - Bootstrap Admin Theme</title>

    <!-- Bootstrap Core CSS -->
    <link href="~/Theme/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">

    <!-- MetisMenu CSS -->
    <link href="~/Theme/vendor/metisMenu/metisMenu.min.css" rel="stylesheet">

    <!-- Custom CSS -->
    <link href="~/Theme/dist/css/sb-admin-2.css" rel="stylesheet">

    <!-- Custom Fonts -->
    <link href="~/Theme/vendor/font-awesome/css/font-awesome.min.css" rel="stylesheet" type="text/css">

    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
        <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
        <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->

</head>

<body>

    <div class="container">
        <div class="row">
            <div class="col-md-4 col-md-offset-4">
                <div class="login-panel panel panel-default">
                    <div class="panel-heading">
                        <h3 class="panel-title">Please Sign In</h3>
                    </div>
                    <div class="panel-body">
                            @using (Html.BeginForm())
                            {
                                @Html.AntiForgeryToken()
                                @Html.ValidationSummary(true, "", new { @class = "text-danger" })
                                <fieldset>
                                    <div class="form-group">
                                        @Html.EditorFor(model => model.Username, new { htmlAttributes = new { @class = "form-control", @placeholder = "Username" } })
                                    </div>
                                    <div class="form-group">
                                        @Html.PasswordFor(model => model.Password, new { @class = "form-control", @placeholder = "Password" })
                                    </div>
                                    <div class="checkbox">
                                        <label>
                                            <input name="remember" type="checkbox" value="Remember Me">Remember Me
                                        </label>
                                    </div>
                                    <!-- Change this to a button or input when using this as a form -->
                                    <input type="submit" class="btn btn-lg btn-success btn-block" value="Login" />
                                </fieldset>
                            }
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- jQuery -->
    <script src="~/Theme/vendor/jquery/jquery.min.js"></script>

    <!-- Bootstrap Core JavaScript -->
    <script src="~/Theme/vendor/bootstrap/js/bootstrap.min.js"></script>

    <!-- Metis Menu Plugin JavaScript -->
    <script src="~/Theme/vendor/metisMenu/metisMenu.min.js"></script>

    <!-- Custom Theme JavaScript -->
    <script src="~/Theme/dist/js/sb-admin-2.js"></script>

</body>

</html>

Please note that you view can be different because I have used a theme on this project also it contains some extra javascripts. You need to parse the logic to your own project.

We can also write some codes for logout action, please see below code for it.

public ActionResult Logout()
        {
            var authManager = HttpContext.GetOwinContext().Authentication;

            authManager.SignOut();

            return RedirectToAction("Login", "Account");
        }
How we are going to use this Authorization in our controller?

We need to add [Authorize(Roles = “Admin”)] if we want our controller should be accessible by only Admin users. Here is the example of usage.

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using DataLibrary;

namespace ReleaseManager.Controllers
{
    [Authorize(Roles = "Admin")]
    public class CategoryController : Controller
    {
    }
}

I have tried to explain the basic implementation and usage of Identity on MVC. We will use this authentication in our sample application later on.

HBN

5 (100%) 10 votes

About the Author: HBN

--Senior QA Engineer-- --Intermediate Web Developer-- --Junior Android Developer--

1 Comment

Leave a Reply

Your email address will not be published. Required fields are marked *