AuthorizationRules Implementation question

AuthorizationRules Implementation question

Old forum URL: forums.lhotka.net/forums/t/5547.aspx


Pawz posted on Monday, October 06, 2008

I've got a bit of a best practices question here in implementing authorization rules, and I'm wondering what you guys think.

Roles & access for users is something that shifts constantly around here - staff shifts around doing different things fairly often. I need to be able to enable / disable access to individual fields and buttons in my application based on each user.

The Project Tracker example has the authorization using a simplistic, hardcoded roles system which wasn't going to work for what I needed. Roles aren't known before hand, so they need to linked up to the database and loaded on a per-user basis.

Anyways, I came up with the following solution:
        protected override void AddAuthorizationRules()
        {
            if (Utils.IsAdmin())
                return;
            foreach (PropertyInfo props in GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) //All public
            {
                AuthorizationRules.AllowRead(props.Name, "AllowRead" + props.DeclaringType.FullName + "." + props.Name);
                AuthorizationRules.AllowWrite(props.Name, "AllowWrite" + props.DeclaringType.FullName + "." + props.Name);
            }
        }


So it looks at itself and for each public property it creates a unique 'role', which matches up with a record in the database - when the user logs in, the user's list of roles is filled with these unique roles - some several thousand of them. It works, but I can't shake the feeling there's a better way to handle it.

Any thoughts would be welcome.




JonStonecash replied on Tuesday, October 07, 2008

Have you thought about writing Custom Principal and Custom Identity classes.  Specifically, overriding the IsInRole method.  There is nothing to prevent you from defining your own set of roles for the application; that is, different roles from those provided by active directory.  These roles could be quite fine-grained: "allowed to access field X".  The Custom Identity could retrieve/fabricate the roles from the database. 

Before I went down that path, I would be inclined to step back and ask what the requirements are.  If it is the case that the application must be able to constrain each user uniquely, I really do not see a much better way than you described.  What you are saying in this case is that there are no patterns of access.  A role is just a pattern of access.  Every user is unique.  This might be true but I would find that quite astonishing.  More likely, there are a fixed number of use cases that define the authorized actions.  If you have defined your use cases, you could define a "role" per use case: Judy is allowed to execute use case Alpha but not use case Beta.  Each use case would define a set of properties that could be accessed.  At this point, patterns of usage start to show up.  The custom Principal and custom Identity could setup those roles from the contents of the database.  My guess is that this would be simpler than what you are doing now.

Jon Stonecash


Pawz replied on Friday, October 10, 2008

Yeah, I've pretty much come to the same conclusion here - in this case, Judy is allowed to execute use case Alpha, but only part of Beta.

In a lot of cases, I can group the behaviours together, so I've allowed for grouping securables together under a 'role', but the role is defined as the collection of items rather than a specifically hardcoded item.

They just love to shift users and roles around here.

stefan replied on Friday, October 10, 2008

Hi,

be aware that the example you posted won't work
Pawz:

        protected override void AddAuthorizationRules()
        {
            if (Utils.IsAdmin())
                return;
            foreach (PropertyInfo props in GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) //All public
            {
                AuthorizationRules.AllowRead(props.Name, "AllowRead" + props.DeclaringType.FullName + "." + props.Name);
                AuthorizationRules.AllowWrite(props.Name, "AllowWrite" + props.DeclaringType.FullName + "." + props.Name);
            }
        }



AddAuthorizationRules is called only once in the apps' lifetime.
So if you follow the PTracker pattern for login/logout, if the user that logged in first was an admin,
there would be no authorizationrules for any other user that would log in later...
You should just add the rules here, and move the IsAdmin check to your custom IsInRole override!


Stefan

Copyright (c) Marimer LLC