mageets
mageets

Reputation: 91

Limiting data modification by User ASP.NET MVC4

I'm building an application in ASP.NET MVC4 as a learning exercise. I'm trying to understand authentication and authorization. That seems fine, role based authorization seems fine for restricting certain controllers/actions to users who are part of a given role.

What I'm struggling with is how I can apply this to data which belongs to an individual user. Using a forum as a simple example how could the functionality be achieved whereby a user can only edit or remove posts that they have created but can view/add comments to posts of other users. Would this have to be done in code by checking the user associated with the post to be updated against the current user before allowing the update to take place, returning unauthorized if they don't match.

Is there a more elegant solution that can be applied rather than applying this kind of logic to multiple controllers/actions?

There's a wealth of information out there I'm just trying to narrow the search. Can anyone suggest a good tutorial/article on this. I've been looking at Forms authentication and Membership but I'd be interested in something using Identity too. I'm also using Entity Framework.

Thanks

Upvotes: 0

Views: 251

Answers (2)

David Brossard
David Brossard

Reputation: 13834

Would this have to be done in code by checking the user associated with the post to be updated against the current user before allowing the update to take place, returning unauthorized if they don't match.

No, you want to avoid hard-coding authorization logic into your code. Doing so leads to:

  • authorization silos
  • poor visibility
  • a chance there might be errors in the authorization logic
  • hard-to-maintain logic

Is there a more elegant solution that can be applied rather than applying this kind of logic to multiple controllers/actions?

Yes, there is. Much like you wouldn't hard-code authentication or logging into your app, you want to externalize authorization. This is called Externalized Authorization Management (EAM). There are several frameworks that help you do that from Spring Security in Java to Claims-based authorization in .NET to XACML-based solutions.

There are 2 fundamental authorization models you want to consider:

  • role-based access control (RBAC)
  • attribute-based access control (ABAC)

You can read about both on NIST's website (RBAC | ABAC).

Given the sample rule you gave:

A user can only edit or remove posts that they have created but can view/add comments to posts of other users.

RBAC will not be enough. You will need to use ABAC (and XACML) to be able to implement the relationship between the user and the data requested. XACML, the eXtensible Access Control Markup Language is a standard that provides you with:

  • a standard architecture.
  • a request/response scheme, and
  • a policy language.

With the XACML policy language, you can rewrite your example as:

  • A user can do the action==edit or the action==remove if and only if the post.owner==user.id
  • A user can do the action==view on any post
  • A user can do the action==comment on any post

Then, from your code, all you have to do is send an authorization request: Can Alice view post #123?. The authorization engine (also called policy decision point or PDP) will determine who owns the post and will reach a decision, either of a Deny or a Permit.

A key benefit to using externalized authorization and XACML is that you can apply the same consistent authorization to any layer (presentation tier, business tier, ESB, APIs, databases...) and any technology (Java, .NET, Python...).

Other benefits include:

  • modular architecture
  • configuration-driven authorization that is easy to grow as requirements change
  • easy-to-audit authorization
  • centrally-managed authorization
  • cheaper to develop and onboard new applications than writing code over and over again
  • standards-based.

There are several open-source and vendor solutions out there that address this market. Have a look at Axiomatics (disclaimer: I work for Axiomatics) or SunXACML (open source).

HTH, David.

Upvotes: 0

Wiktor Zychla
Wiktor Zychla

Reputation: 48230

Would this have to be done in code by checking the user associated with the post to be updated against the current user before allowing the update to take place, returning unauthorized if they don't match.

Yes, that's exactly what you do. While role-based authorization is a matter of a simple relation between users and roles, data-access level authorization is usually complex and involve custom business rules.

Of course, it could help a lot to create a thin layer of managers that will be commonly used as guards so that you keep all the code close together:

 [HttpPost]
 public ActionResult PostFoo( FooModel model )
 {
     // keep the access manager separate from the
     // domain layer. operate on IDs.
     if ( new UserAccessManager( this.User ).
        CanOperateOnFoo( model.IdSomething, model.IdWhateverElse ) )
     {
     }
     else
        // return 403 or a meaningful message  
 }

or

 [HttpPost]
 public ActionResult PostFoo( FooModel model )
 {          
     // switch to the domain layer
     Foo foo = Mapper.Map( model );

     // make the access manager part of the domain layer
     if ( foo.CanBeOperatedBy( this.User ) )
     {
     }
     else
        // return 403 or a meaningful message  
 }

Upvotes: 1

Related Questions