Mike Croteau
Mike Croteau

Reputation: 1132

Permission based authorization .net identity

I am new to .NET, MVC & Identity Framework. I noticed the identity framework allows for securing individual controller actions via annotations.

[Authorize]
public ActionResult Edit(int? Id){
    //edit action
}

I would like to secure certain actions based on user permissions.

Example : A blog application where only the user who created a blog post can edit.

With this in mind, is it possible to perform either option below? If so, are there resources and examples on how to best achieve?

[Authorize(Entity = "Entry", Permission = "Edit", Id = Id)]
public ActionResult Edit(int? Id){
    //edit action
}

or

[BlogEntryPermission(Permission = "Edit", Id = Id)]
public ActionResult Edit(int? Id){
    //edit action
}

Where blog Id is captured from the request.

Any information or direction on permission based authentication would be most appreciated. Thanks in advance for your help.

Upvotes: 9

Views: 11929

Answers (3)

Armin Khodaei
Armin Khodaei

Reputation: 141

I hope your problem solved till now. But worth it to add a new solution. I've implemented a Permission-based extension for Microsoft Identity 2 membership system. It's an open source project and you can access to the repository here:

https://github.com/Arminkhodaei/Identity-Permission-Extension

Usage:

First approach:

// GET: /Manage/Index
[AuthorizePermission(Name = "Show_Management", Description = "Show the Management Page.")]
public async Task<ActionResult> Index(ManageMessageId? message)
{
    //...
}

Second approach:

// GET: /Manage/Users
public async Task<ActionResult> Users()
{
    if (await HttpContext.AuthorizePermission(name: "AllUsers_Management", description: "Edit all of the users information."))
    {
        return View(db.GetAllUsers());
    }
    else if (await HttpContext.AuthorizePermission(name: "UnConfirmedUsers_Management", description: "Edit unconfirmed users information."))
    {
        return View(db.GetUnConfirmedUsers());
    }
    else
    {
        return View(new List<User>());
    }
}

Upvotes: 1

Vsevolod Goloviznin
Vsevolod Goloviznin

Reputation: 12324

You can implement your custom AuthorizationAttribute where you will specify your parameters and can get a blogId from request

public class AuthorizeEntryPermission : AuthorizeAttribute
{
        public string Permission { get; set; }

        public AuthorizeEntryPermission(){
        }

        public AuthorizeEntryPermission(string Permission)
        {
            this.Permission = Permission;
        }

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
             var id = context.Request.RequestContext.RouteData.Values["Id"];
             //check your permissions
        }

        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (AuthorizeCore(filterContext.HttpContext))
            {
                // ** IMPORTANT **
                // Since we're performing authorization at the action level, the authorization code runs
                // after the output caching module. In the worst case this could allow an authorized user
                // to cause the page to be cached, then an unauthorized user would later be served the
                // cached page. We work around this by telling proxies not to cache the sensitive page,
                // then we hook our custom authorization code into the caching mechanism so that we have
                // the final say on whether a page should be served from the cache.

                HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
                cachePolicy.SetProxyMaxAge(new TimeSpan(0));
                cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
            }
            else
            {
                //handle no permission
            }
        }

        private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus)
        {
            validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
        }
    }

Then use it like this:

[AuthorizeEntryPermission(Permission = "Edit")]
public ActionResult Edit(int? Id){
    //edit action
}

Upvotes: 6

NightOwl888
NightOwl888

Reputation: 56859

MVC has roles built-in. You can make the roles as granular as you need - essentially making them like permissions. For example, you could make role names like:

  • EditBlogPost
  • AddBlogPost
  • ViewBlogPost

Then you can set the roles up on your controller using the built-in AuthorizeAttribute.

[Authorize(Roles = "AddBlogPost")]
public ActionResult Add(){
    //add action
}

[Authorize(Roles = "AddBlogPost")]
[HttpPost]
public ActionResult Add(BlogModel model){
    //add action
}

[Authorize(Roles = "EditBlogPost")]
public ActionResult Edit(int? Id){
    //edit action
}

[Authorize(Roles = "EditBlogPost")]
[HttpPost]
public ActionResult Edit(BlogModel model){
    //edit action
}

[Authorize(Roles = "ViewBlogPost")]
public ActionResult View(){
    //view action
}

Then it is just a matter of assigning the different roles to each user in your database.

Upvotes: 1

Related Questions