12
votes

Currently I’m developing an ASP.Net MVC 5 application with MS Sql server database. I need to implement authentication and authorization based on ASP.Net identity 2.0. I just went through basic concepts of Identity and try to implement the same in my application. Since the database is already defined, I need to customize Identity a little bit. When I looked on to the database, tables are little bit different that I normally found in sample identity projects.

enter image description here

From the image you can see that there is a table named user group and defined set of rights to them based on module. The same rights will be accessible to the user by default. If you want to change any rights you can override it by setting permission in User Rights table.

So my first question is, ASP. Net Identity with Custom Authorization and Authorization is the right method to implement a scenario like this?

From the view perspective, I have to generate a menu based on user / user group rights and also want to enable / disable buttons based on them. I was able to generate menu based on database values. But I need to authorize each and every client request and for that I think AuthorizeAttribute is the best option. Please suggest? Any good design patterns or post are appreciated.

1

1 Answers

18
votes

Sure Identity so powerful and flexible you can customized it. Use your user right as a claim then write a customized AuthorizeAttribute to check the claims for example consider this code:

[HttpPost]
public ActionResult Login(string username, string password)
{
    if (_userManager.IsValid(username, password)) // your own user manager 
    {
        var ident = new ClaimsIdentity(
          new[] 
          {
              // adding following 2 claim just for supporting default antiforgery provider
              new Claim(ClaimTypes.NameIdentifier, username),
              new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string"),

              new Claim(ClaimTypes.Name, username),
              // populate assigned user rightID's form the DB and add each one as a claim  
              new Claim("UserRight","FirstAssignedUserRightID"),
              new Claim("UserRight","SecondAssignedUserRightID"),
          },
          DefaultAuthenticationTypes.ApplicationCookie);

        HttpContext.GetOwinContext().Authentication.SignIn(
           new AuthenticationProperties { IsPersistent = false }, ident);
        return RedirectToAction("MyAction"); // auth succeed 
    }
    // invalid username or password
    ModelState.AddModelError("", "invalid username or password");
    return View();
}

And write the claim based authorize attribute:

public class ClaimsAccessAttribute : AuthorizeAttribute 
{
    // in the real world you could get claim value form the DB, 
    // I simplified the example 
    public string ClaimType { get; set; }
    public string Value { get; set; }

    protected override bool AuthorizeCore(HttpContextBase context) 
    {
        return context.User.Identity.IsAuthenticated
            && context.User.Identity is ClaimsIdentity
            && ((ClaimsIdentity)context.User.Identity).HasClaim(x =>
                x.Type == ClaimType && x.Value == Value);
    }
}

At the end you just need to add your attribute to your actions:

[ClaimsAccess(CliamType="UserRight",Value="YourRightID"]
public ActionResult MyAction()
{
    // also you have access the authenticated user's claims 
    // simply by casting User.Identity to ClaimsIdentity
    // ((ClaimsIdentity)User.Identity).Claims
}

I omitted user group to simplify the example and also I hardcoded some parts which you need to write a provider to fetch from DB.