locked
Extending Membership API vs. Custom Authorization RRS feed

  • Question

  • User307147791 posted

    I have a particularly thorny security problem in which I am debating extending the membership API vs. creating my own custom authorization "framework".  I have an ASP.NET 3.5 web application with contain several pages, one of which hosts a Flex application we are developing. This Flex application communicates with web services we have developed contained within the same ASP.NET 3.5 web application. We are securing the web application (and services) using Forms Authentication which works well for authentication. However, our security model is quite flexible and I do not think the current membership API is up to the task of handling this model.

    Our security model contains users, roles, and permissions (actions).  Users are self explanatory. Roles can be created and deleted through the application by appropriately privileged users, however roles do not directly determine what restrictions a user has. This is accomplished via a finite list of permissions. These permissions define every action that is possible within the application such as create user, delete user, view report, create report, delete report, etc.  So, a user is assigned to one or more roles, and a role contains one or more permissions. This allows the administrator of the application to define any number of roles with terminology specific to their organization. However, for every action we need to determine if the currently logged in user has permissions to perform that action.

    The membership API assumes that roles restrict functionality, however in our application that is not the case. So, the question that I have is whether or not I should attempt to extend the membership API to support this workflow or if I would be better off writing a couple of classes to manage the authorization myself. Perhaps I could create a custom IPrinciple to support a IsAuthorized(string action) method, or I could go higher still and create a method such as AuthHelper.IsAuthenticated(string user, string action).

     Eventually, our application will require record level permissions as well and so I do not feel that the membership API is an appropriate choice.

     Thoughts or suggestions?

    Tuesday, July 1, 2008 2:49 PM

Answers

  • User1564875471 posted

    I think its better to work with the built in membership and roles without creating a custom providers , create a class that provider you with a list of required API's to check the user / role permisison .

    so you could create an Enumeration that contains the list of permisisons ( the permissions must be predefined and can't changed without rebuilding the code ) ,

    public Enum PermissionType

     CreateUser=1

    ViewReport=2

    .....

    End Enum

    This is much easier than working with the permission as a string .

    So Create a FineGrained Class that wraps all the complexities of checking the user permisions ....

    I don't recommended to create a custom Principal , because it requires more work and you will have to cast the generic principal every time you want to accees  your custom methods / properties .

    Also , a custom Identity is not required because you can can get the user properties by calling Membership.GetUser  which returns the user name, email ....

     

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, July 5, 2008 3:41 PM

All replies

  • User307147791 posted

     So, I have been putting a little more thought into this and I thought it would be helpful if a provide more concrete details about my requirements. We can look at a few of the required web pages below.

    • /Login.aspx - The login page.
    • /Default.aspx - The start page. Links to other pages in the application.
    • /Flash.aspx - Hosts the Flex application which communications with SOAP web services in the /Services/ directory
    • /Services/ - Folder containing services
      • /Report.aspx - Services to allow a user to create, view, edit, print various reports

    I want to be able to secure these pages based on permissions that have been granted to a user. Permissions are not granted by Role but by a fine grained (and predetermined) permissions list maintained in a database table. I do define roles as it is easier to assign P permissions to a role, and then assign U users to the role. Users can belong to more than one role.  Permissions can belong to more than one role. This creates tables that roughly look like this.

    User
    UserID
    UserName
    PasswordHash
    PasswordSalt
    Role
    RoleID
    RoleName
    Description
    Permission
    PermissionID
    PermissionName
    Description
    UsersInRoles
    UserID
    RoleID
    PermissionsInRoles
    PermissionID
    RoleID

    Page access would then be restricted based on a permission rather than a role. For instance, I would like to be able to call something like User.IsAuthorized("CREATE_USER") to determine if the logged in user is able to create the user.  Or perhaps I could call User.IsAuthorized("VIEW_REPORT") to see if the user can view reports.In each of these cases, the string passed in is fine grained permission found in the Permission table.  Of course I will need administration pages to create users, create roles, assign users to one or more roles, and assign permissions to one or more roles.  The membership API does have some of this functionality, however it is not fine grained enough to do what I am trying to do so I either need to extend the membership provider implementation or write my own from scratch.

    I also need to this to work well with web services. The Flash application on the Flash.aspx page communicates with the server via SOAP web services. I have found that when I use Forms authentication to secure the website the attached authentication token/cookie is also sent to my web services from the Flash application and so I am able to determine the logged in user within the context of a SOAP web service.

     So, with this added information does anyone think that the current membership model is up to the task with a little enhancement?  Should I just try to create my own providers (User, Role, Permission) from scratch? Or should I stick with the tried and trusted (though crusty) collection of static methods to retrieve this information from the database on each request? What about creating custom a custom Principal? 

     I have been reading and researching a lot but I would like some feedback from the community, and perhaps we can get a discussion going.  I find that I have several paths to follow and I am not sure which one is the best one for given the scope of my application.

    Saturday, July 5, 2008 1:03 PM
  • User307147791 posted

     I would like to add that I would like to try to keep the authentication mechanisms as separate as possible from the authorization mechinims.  Ideally I could use Windows Authentication with my authorization store as easily as I can with Forms Authentication.

    Saturday, July 5, 2008 1:13 PM
  • User-2008565010 posted

    as per my understanding .. Authorization Manager(AzMan) has mechanism where you can grant access based on operation level permission...

    see if that can give you some more hints... 

    Saturday, July 5, 2008 1:55 PM
  • User307147791 posted

     I had found AzMan when I was looking around it some aspects of it fit nicely, however I should add that I will not be able to use AzMan as I will need to install this application in various client sites as potential intranet solutions (in addition to our hosted internet solution).  It is doubtful that I will be able to install AzMan on our client's servers and integrate with their Active Directory if they have one.  From what I see regarding AzMan it doesn't appear to have a database backend component and the API to determine whether or not a user has permissions for a particular actions seems quite cumbersome.  This information is from http://msdn.microsoft.com/en-us/library/ms998336.aspx.

    Saturday, July 5, 2008 2:13 PM
  • User1564875471 posted

    I think its better to work with the built in membership and roles without creating a custom providers , create a class that provider you with a list of required API's to check the user / role permisison .

    so you could create an Enumeration that contains the list of permisisons ( the permissions must be predefined and can't changed without rebuilding the code ) ,

    public Enum PermissionType

     CreateUser=1

    ViewReport=2

    .....

    End Enum

    This is much easier than working with the permission as a string .

    So Create a FineGrained Class that wraps all the complexities of checking the user permisions ....

    I don't recommended to create a custom Principal , because it requires more work and you will have to cast the generic principal every time you want to accees  your custom methods / properties .

    Also , a custom Identity is not required because you can can get the user properties by calling Membership.GetUser  which returns the user name, email ....

     

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, July 5, 2008 3:41 PM
  • User307147791 posted

    Anas,

    I totally agree about the enumeration. That would be far easier than remembering (or looking up) a bunch of strings. I had planned to do something about the strings, but had not yet gotten that far in my thought process.

    If I understand correctly, you would work with the APIs as they are rather than extending them. I was thinking about extending the RoleProvider to allow me to easily add Permissions to the Roles.  Something along the lines of this:

    Roles.AddPermissionToRole(PermissionType permission, string role);
    Roles.AddPermissionToRoles(PermissionType permission, string[] roles);
    Roles.AddPermissionsToRole(PermissionType[] permissions, string role);
    Roles.AddPermissionsToRoles(PermissionType[] permissions, string[] roles);

    I also wanted to extend the MembershipUser to allow me to check the Role/Permission more easily, something as easy as MembershipUser.IsAuthorized(PermissionType.CreateUser). But is sounds like this you would not recommend this. And, when looking at the default MembershipUser properties and methods, it doesn't seem like it is meant for Authorization.  It seems like the Principal and RoleProvider are used for this.  In any case, I am not very familar with the pros/cons of the membership API (though I am trying to catch up as fast as I can) so I am curious as to why you might not recommend extending the membership API as described above.

    I must admit that I am struggling to find where the usefulness of the membership API begins and ends in regards to my application.  It is nice that it provides as much as it does out of the box, and it is pretty awesome that with a proper provider I can change databases without altering anything in the application. Especially since this application will eventually be supported on SQL Server, Oracle and PostgreSQL (starting with PostgreSQL). However, this all comes at a cost of complexity, mainly in the database schema and API. It is constructed to be incredibly configurable, and as such there are tables and fields (and class members and properties) that I would not use. It seems like this may cause confusion for the maintainers of the system.  And so, I think that is my struggle.  Ease of use vs. versatility.  Convention vs. configuration.

     Perhaps you may be able to shed more light on this?


    Saturday, July 5, 2008 5:17 PM
  • User1683967925 posted

    Hi, I'm working on a similar problem. What was your solution in the end?

    Steve. 

    Thursday, March 18, 2010 3:04 PM