I'm wrestling with building a custom membership provider that allows me to have the security scheme I need.
I have my own IPrincipal, IIdentity, and MembershipProvider. I have the authentication working fine. The problem I'm running into now is the authorization.
The problem I have with the authorization scheme is inherintly in the IPrincipal's IsInRole behavior. This behavior is tightly coupled to various features of ASP.NET Webforms, my main concern being the sitemap authorization, because I'd like to use it if I can.
So you might traditionally have a sitemap like so:
<siteMap xmlns="blahblah">
<siteMapNode url="PersonView.aspx"
title="View Person"
description="View the details of a person"
roles="ViewerRole" />
</siteMap>
Here, anyone trying to go to the PersonView.aspx page will be required to have the ViewerRole. This is where my problem arises. I don't want to have my authorization tied to a user's role. Instead, I want the authorization to be tied to the behavior I'm performing and let some underlying thing behind the scenes take care of the authorization.
So what I really want is something like this instead:
<siteMap xmlns="blahblah">
<siteMapNode url="PersonView.aspx"
title="View Person"
description="View the details of a person"
roles="Person|View" />
</siteMap>
This should be interpreted as anyone trying to go to the PersonView.aspx page must have View rights to the Person business object.
I already have an Authorizer object which has a signature like so:
public static bool Authorize(Type type, Access access, IUser user)
Which will take, for instance, the Person type, the View access (enum), and the user to check it against. Now, I have the code inside the Authorize figured out.
My problem is, how do I get from the IPrincipal's IsInRole to my Authorize? I've tried different things but none of them seem to work. I really don't like the magic string approach, but it seems like I'm stuck with it. If there was a way to build it in a strongly typed manner I would definitely prefer that instead. Is there a better way to do this that I'm not thinking of?