0

I have created an enum with security access levels, an example:

public enum AccessLevel
{
    Total,
    DeletionPrivileges,
    MaintainUsers,
    MaintainInventory,
    QueriesOnly,
    None
}

I can manage the site so certain features eg delete, are not presented to someone without deletion privileges. But I am also wanting to use some kind of authorisation within the code.

Within the default framework, there is the facility to prevent access to certain areas of a project using [Authorize], how can I create differing levels of authority to tag each method?

1
  • Are you using Identity for authentication? Commented Sep 10, 2015 at 11:32

1 Answer 1

2

You could use claim based authentication feature of Identity to aim this purpose easily. First you need add proper claim per user in log in action method to do this change your log in action method like this:

[HttpPost]
public ActionResult Login(LoginViewModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        var userManager=HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
        var user = userManager.Find(model.UserName, model.Password);
        if (user != null)
        {
            var ident = userManager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie);

            // imaging you have a custom class which return user access levels 
            var userAccessLevels=_accessLevelManager.GetAccessLevels(user.Id);
            // now we are going to add our custom claims 
            ident.AddClaims(new[]
            {
                // add each access level as a separate claim 
                new Claim("AccessLevel",userAccessLevels[0].ToString()),
                new Claim("AccessLevel",userAccessLevels[1].ToString()),
                // and so on
            });
            HttpContext.GetOwinContext().Authentication.SignIn(new AuthenticationProperties { IsPersistent = false }, ident);
            // authentication succeed do what you want 
            return Redirect(login.ReturnUrl ?? Url.Action("Index", "Home"));
        }
    }
    ModelState.AddModelError("", "Invalid username or password");
    return View(login);
}

Now we have successfully injected our claims to Identity. But you need a custom authorize attribute to check your claims like this:

public class ClaimsAccessAttribute : AuthorizeAttribute 
{
    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);
    }
}  

Now you could easily use your attribute in your action methods:

[ClaimsAccess(CliamType="AccessLevel",Value="DeletionPrivileges")]
public ActionResult MyAction()
{
    // also you have access the authenticated user's claims 
    // simply by casting User.Identity to ClaimsIdentity
    // ((ClaimsIdentity)User.Identity).Claims
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.