views:

23

answers:

1

Summary: I need to authorize pages based upon the data present in the query string of a url, not just the page name.


Background:

Let's say I'm building a library inventory system. Users can be created and assigned to a single library in either an Admin or User role. There are hundreds of competing libraries in the same database, so it's important to ensure that users of one library cannot view inventory from another library.

Right now I'm using a pretty standard ASP.NET setup: Forms Authentication using the SqlMembershipProvider. Authorization using the SqlRoleProvider, configured via <authorization> sections in the web.config. Security trimming with the SiteMap provider to hide unauthorized pages.

To control the inventory information from leaking, I'm manually checking a user's associate library ID with every inventory query. It works, but it's tedious and prone to errors. There has to be a better way.

Question:

Now users have the ability to create arbitrary "collections" within a library. (e.g. Collection A has Books 1, 2, & 3 in it.) Admins want the ability to grant Admin / User access on individual collections, not just the entire library.

So, if a user goes to www.com/Book.aspx?BookId=1, the system needs to ensure that user has permissions for the collection that "Book 1" is in before showing the page. If they go to www.com/Reviews.aspx?ReviewId=23, I need to make sure the Review is for a book that is in a collection that they have permission to view.

1) How can I implement this in the most standard ASP.NET way possible?
Manual checking within a base page?
A custom HttpModule?
A custom Role Provider?
I'm not interested in how to store the admin/user permissions, but rather how/where to authorize based on those permissions. (examples on how to implement any of those are appreciated)

2) To further complicate it, I'd still like security trimming to check if the user has Admin rights on any collection or library and hide the admin pages if he doesn't.

+1  A: 

I wouldn't handle this anywhere near the UI (ASP.NET) layer but rather within the application services. Something like:

a) Build services which take an IPrincipal (or your custom user object) as a constructor parameter.
b) When requesting a book/review/whatever, the service is responsible for looking to checking to see if the user has access to the resource.
c) If the user doesn't have access, do some predetermined thing (pass a message, throw an exception, return null).

This will be alot more testable and usable in the long run then worrying about it from the ASP.NET UI side.

If you have to handle it on the ASP.NET side, I'd consider using a custom IPrincipal and custom RoleProvider to wrap up each library as a role to access, then you could use most of the LoginView, etc. controls.

Wyatt Barnett
+1 Those are very good points. If it throws an exception, and I forget to handle it in the UI, at worst it'll crash instead of leaking sensitive data (which is a good thing).
Greg