Asp.Net MVC 5 authentication and authorization using claims principal

Asp.Net MVC 5 authentication and authorization using claims principal :-


Step1 :

File -> New Project -> Asp.Net Web Application -> Asp.Net 4.5.2 Templates

Choose empty MVC project template

Step2 :

Install following nuget packages

Microsoft.AspNet.Identity.Core

Microsoft.AspNet.Identity.Owin

Microsoft.Owin

Microsoft.Owin.Host.SystemWeb

Microsoft.Owin.Security

Microsoft.Owin.Security.Cookies

Microsoft.Owin.Security.OAuth

Owin

Step3 :

Create a Owin Startup class and decorate with assembly attribute OwinStartup.

using Microsoft.AspNet.Identity;

using Microsoft.Owin;

using Microsoft.Owin.Security.Cookies;

using Owin;


[assembly: OwinStartup(typeof(AspNetMVC5Authorization.Startup))]  // here "AspNetMVC5Authorization" is the name of project


namespace AspNetMVC5Authorization

{

public class Startup

{

public void Configuration(IAppBuilder app)

{

ConfigureAuthentication(app);

}


private void ConfigureAuthentication(IAppBuilder app)

{

app.UseCookieAuthentication(new CookieAuthenticationOptions

{

AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,

LoginPath = new PathString("/Auth/Login"), //sign page

CookieName = "AuthCookie",

CookieHttpOnly = true,

ExpireTimeSpan = System.TimeSpan.FromHours(1),

LogoutPath = new PathString("/Auth/Signout"), //sign out page

ReturnUrlParameter = "ReturnUrl",

CookieSecure = CookieSecureOption.SameAsRequest, //Use CookieSecureOption.Always if you intend to serve cookie in SSL/TLS (Https)

SlidingExpiration = true,

});

}

}

}

Step4 :

Create list of claims for the specific user with roles and other information

internal class AuthenticationHelper

{

   internal static List<Claim> CreateClaim(UserSessionModel userSessionModel,params string[] roles) //Single or multiple roles

   {

  var claims = new List<Claim>

  {

  new Claim(ClaimTypes.NameIdentifier, userSessionModel.UserId.ToString()),  //User ideitifer

  new Claim(ClaimTypes.Name, userSessionModel.DisplayName),  //Username

  new Claim(Constants.UserSession, userSessionModel.ToJson()) //Custom entity with user info

  };


  foreach (var role in roles) //custom roles goes here

  {

  claims.Add(new Claim(ClaimTypes.Role, role, ClaimValueTypes.String, Constants.Issuer));

  }

  return claims;

   }

}

Step5 :

Create Authentication controller and process of the rest of the Authentication

namespace AspNetMVC5Authorization.Controllers

{

using Microsoft.AspNet.Identity;

using Microsoft.Owin.Security;

using System;

using System.Security.Claims;

using System.Web;

using System.Web.Mvc;

using Helpers;

using ViewModels;


public class AuthController : BaseController

{

[HttpGet]

public ActionResult SignIn()

{

if(UserSessionModel != null)

{

return Redirect("~/");

}

return View();

}


[HttpPost,ValidateAntiForgeryToken]

public ActionResult SignIn(SignInViewModel vm,string returnUrl = default(string))

{

try

{

if (!ModelState.IsValid)

{

vm.ErrorMessage = "Email address and Password are required fields";

return View(vm);

}


Authenticate(vm);


if (!string.IsNullOrWhiteSpace(returnUrl) && Url.IsLocalUrl(returnUrl))

{

return Redirect(returnUrl);

}


return RedirectToAction("index", "home");

}

catch (AuthenticationException e)

{

vm.ErrorMessage = e.Message;

}

return View(vm);

}


private void Authenticate(SignInViewModel vm)

{

if (vm.Email == "admin@gmail.com" && vm.Password == "password")

{

var userSession = new UserSessionModel

{

UserId = Guid.NewGuid(),

DisplayName = "Admin user",

UserRoleId = 1,

UserRoleName = "Admin"

};


var identity = new ClaimsIdentity(AuthenticationHelper.CreateClaim(userSession,

Helpers.Constants.UserRoles.Admin,

Helpers.Constants.UserRoles.User),

DefaultAuthenticationTypes.ApplicationCookie

);

AuthenticationManager.SignIn(new AuthenticationProperties()

{

AllowRefresh = true,

IsPersistent = true,

ExpiresUtc = DateTime.UtcNow.AddHours(1)

}, identity);

}

else if (vm.Email == "user@gmail.com" && vm.Password == "password")

{

var userSession = new UserSessionModel

{

UserId = Guid.NewGuid(),

DisplayName = "User user",

UserRoleId = 2,

UserRoleName = "User"

};


var identity = new ClaimsIdentity(AuthenticationHelper.CreateClaim(userSession,

Helpers.Constants.UserRoles.User),

DefaultAuthenticationTypes.ApplicationCookie

);

AuthenticationManager.SignIn(new AuthenticationProperties()

{

AllowRefresh = true,

IsPersistent = true,

ExpiresUtc = DateTime.UtcNow.AddHours(1)

}, identity);

}

else

{

throw new AuthenticationException("Login failed. Incorrect email address or password");

}

}


public ActionResult Signout()

{

AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie,DefaultAuthenticationTypes.ExternalCookie);

return Redirect("~/");

}


private IAuthenticationManager AuthenticationManager

{

get { return HttpContext.GetOwinContext().Authentication; }

}

}

}


Step6 :

Get the custom ojbect obect from Claim

public class BaseController : Controller

{

protected internal UserSessionModel UserSessionModel { get; private set; }


protected override void Initialize(RequestContext requestContext)

{

base.Initialize(requestContext);

var user = User as ClaimsPrincipal;

if (user != null)

{

var claims = user.Claims.ToList();

var sessionClaim = claims.FirstOrDefault(o => o.Type == Constants.UserSession);

if (sessionClaim != null)

{

UserSessionModel = sessionClaim.Value.ToObject<UserSessionModel>();

}

}

}

}


Step7 :

namespace AspNetMVC5Authorization.Helpers

{

internal static class Constants

{

internal const string UserSession = "UserSession";


internal const string Issuer = "https://yoursite.com";


internal static class UserRoles

{

internal const string Admin = "Admin";


internal const string User = "User";

}

}

}

Step8 :

namespace AspNetMVC5Authorization.Helpers

{

using Newtonsoft.Json;

public static class JsonSerializer

{

public static string ToJson<T>(this T t)

{

return JsonConvert.SerializeObject(t);

}


public static T ToObject<T>(this string data)

{

return JsonConvert.DeserializeObject<T>(data);

}

}

}

Step9 :

using System.Security.Claims;

using System.Web.Mvc;


namespace AspNetMVC5Authorization.Controllers

{

[Authorize(ClaimType = ClaimTypes.Role, ClaimValue = Helpers.Constants.UserRoles.Admin)]

public class AdminController : BaseController

{

// GET: Admin

public ActionResult Index()

{

return View();

}

}

}

Step10 :

using System.Security.Claims;

using System.Web.Mvc;


namespace AspNetMVC5Authorization.Controllers

{

[Authorize(ClaimType = ClaimTypes.Role, ClaimValue = Helpers.Constants.UserRoles.Admin + "," + Helpers.Constants.UserRoles.User)]

public class UserController : BaseController

{

// GET: User

public ActionResult Index()

{

return View();

}

}

}


Step11 :

Custom Authorize attribute code 

namespace AspNetMVC5Authorization

{

using Helpers;

using System;

using System.Linq;

using System.Security.Claims;

using System.Web.Mvc;


[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]

public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute

{

public string ClaimType { get; set; }

public string ClaimValue { get; set; }


public override void OnAuthorization(AuthorizationContext filterContext)

{

base.OnAuthorization(filterContext);

var principal = filterContext.RequestContext.HttpContext.User as ClaimsPrincipal;

if (!principal.Identity.IsAuthenticated)

{

filterContext.Result = new RedirectResult("~/auth/signin");

return;

}


var claimValue = ClaimValue.Split(',');

if (!(principal.HasClaim(x => x.Type == ClaimType && claimValue.Any(v => v == x.Value) && x.Issuer == Constants.Issuer)))

{

filterContext.Result = new RedirectResult("~/Unauthorize.html");

}

}

}

}

Step12 :

Master page 

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>ASP.NET Identity Application</title>

<link href="~/Content/Site.css" rel="stylesheet" type="text/css" />

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">

<script src="~/Scripts/modernizr-2.6.2.js"></script>

</head>

<body>

<div class="navbar navbar-inverse navbar-fixed-top">

<div class="container">

<div class="navbar-header">

<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">

<span class="icon-bar"></span>

<span class="icon-bar"></span>

<span class="icon-bar"></span>

</button>

@Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })

</div>

<div class="navbar-collapse collapse">

<ul class="nav navbar-nav navbar-right">

@if (HttpContext.Current.User.Identity.IsAuthenticated)

{

<li class="dropdown">

<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="glyphicon glyphicon-user"></i><span>&nbsp;</span>@HttpContext.Current.User.Identity.Name<b class="caret"></b></a>

<ul class="dropdown-menu">

<li><a href="#">Profile</a></li>

<li class="divider"></li>

<li><a href="#">Change Password</a></li>

<li class="divider"></li>

<li><a href="/auth/signout">Sign out</a></li>

</ul>

</li>

if (HttpContext.Current.User.IsInRole("Admin")) // ye Helpers.Constants.UserRoles ke andar jo property ke naam ki value de rkhi he uske base pr ye work kr rha he.

{

<a href="#">Hello I am admin link</a>

}

}

else

{

<li class="dropdown">

<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="glyphicon glyphicon-user"></i>&nbsp; <b class="caret"></b></a>

<ul class="dropdown-menu">

<li><a href="/auth/signin">Sign In</a></li>

</ul>

</li>

}

</ul>

</div>

</div>

</div>


<div class="container body-content">

@RenderBody()

<hr />

<footer>

<p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>

</footer>

</div>


<script src="~/Scripts/jquery-1.10.2.min.js"></script>

<script src="~/Scripts/bootstrap.min.js"></script>

</body>

</html>

 

Comments

Popular posts from this blog

Call CRUD(GET, POST, PUT, DELETE) API using WebClient in c#