Object-oriented – Correct Way to Implementing Authorization Checks in ASP MVC

asp.net-mvc5authorizationobject-orientedpermissionsroles

In ASP MVC we have the Authorize attribute to perform check at either a controller level or at a controller method level. But what if you need to do check permissions inside a controller method e.g let say your doing some update or create action to submit a blog post. Some users with revant permissions can attach files or make the blog post sticky. So when you are creating a new post you need to do all these additional check before saving the model. In Laravel there is the concept of abilites where you can do checks inside a controller method to see if a user has the ability to perform the relevant actions. Similarly you can use those abilitis inside views to check what item to display or hide – all this comes out of the box.

Is there anything similar in ASP MVC. How would you implement checking permissions within a controller method. Do you create a permission class with properties such as

public class Permissions
{
    private readonly IPrincipal user;

    public Permissions (IPrincipal user)
    {
        this.user = user;
    }

    public bool CanUploadFiles
    {
        get { return user.IsInAnyRole("Standard", "Admin"); }
    }

    public bool CanDeleteItems
    {
        get { return user.IsInRole("Admin"); }
    }

     public bool CanLockPost
    {
        get { return user.IsInRole("Admin"); }
    }

    // other permissions
}

Then inside controller action:

 public ActionResult Create(PostViewModel viewModel)
 {
       var permissions = new Permissions(User);

        if (ModelState.IsValid)
        {
                var post = new Post
                {
                   if (permissions.CanLockPost)
                    {
                        post.IsLocked = viewModel.IsLocked;
                    }
                    if (permissions.CanStickyPost)
                    {
                        post.IsSticky = viewModel.IsSticky;
                    }
                    // Set other properties
                }

               _postRepository.Add(post);
        }   
  }

Or would you save permissions in the database. I would like to hear your thoughts on how you go about implementing checks at a more granular level than simply at a controller or controller action level. Some code examples to demonstrate would be helpful.

Best Answer

Take a look at this: https://docs.asp.net/en/latest/security/authorization/roles.html

"How these roles are created and managed depends on the backing store of the authorization process. Roles are exposed to the developer through the IsInRole property on the ClaimsPrincipal class."

So as long as you're using the IsInRole() of the principal to check roles, I think you're are on the right track.

Some other random thoughts for you - To make it easier to use your permissions checks, if they are specific to a view model, you could expose them in the view model class. That way the razor view can check the view model to see what it should/shouldn't show to the user.

You could also use those same permissions checks to throw validation errors by implementing IValidatableObject in the view model class and putting your custom checks in the Validate method. Then you can handle permissions errors that prevent saving just like validation errors.