I am working on my first .NET development project that involves custom role-based security per the project requirements. This lead to a general design issue this week that really caused us some concern. I have described the situation below because we are very curious to see what other, more experienced, developers might suggest. The specific classes and fields are used just to illustrate the concepts. Our application uses role-based authorization security. Thus, we allow the administrator to define roles to which the can define various permissions. Permissions are defined relative to the various entities in the application, such as Users, Customers, Services, etc. One such role might be defined as follows: Role: Administrator Permissions: Add User, Delete User, View User, Update User Thus a user that is added to the Administrator role is granted permission to add, delete, view and update User entities. Once such a user is authenticated, they will be authorized to perform those actions. Now, consider that the User entity is abstracted by a User class, and suppose that class has a Username field (among others). If an authenticated user indicated that they would like to edit the Username field of a system User entity, the system first checks to see what role the authenticated user is in. If they are in an administrator role, they have the desired "Update User" privilege described above, so the system instantiates a User object and presents it to the user for editing. If, however, the user does not have this permission, their request is denied and the system does not instantiate an object. So far, so good. Now, suppose that another requirement is that ANY user that is logged into the system must be granted permission to edit their own Username, regardless of what role they are in. In otherwords, the currently authenticated user should always be granted the ability edit their own Username. Now, here is where we ran into a problem. If the currently authenticated user would like to update their Username field, but they are not in an Administrator role, the system will not allow the User object to be instantiated, so they will not be able to edit their Username as desired. The object that provides the functionality needed is not accessible. As we began to think about this situation, it was not clear how best to solve the problem and it lead to quite a bit of discussion. Naturally, we wondered if this is a common problem for which there is a consensus solution in the developer community, or whether there was just something inherently wrong with our role-based security model, our object model or our logic. Here are some of the solutions we considered. I was hoping to hear what others think. 1. Create a hidden "System" role which has all possible permissions. Add a hidden "System" user to this role. Anytime such a situation occurs, log out the current user, log in the System user, perform the desired actions, then log the current user back in. 2. Create a different class, with different security logic, that can be used to expose the proper Username field to the currently authenticated user for editing. This would mean that a single field in the DB would be editable through two different classes. 3. Add additionaly security logic to the User class such that it functions as follows: If the authenticated user requesting a User object has Update User permission, instantiate the requesed User object. If the authenticated user does not have Update User permission, allow them the ability to instantiate only the User entity that corresponds to themselves, and expose only the Username field for editing (make all other fields read-only). Any thoughts on the problem in general or the possible solutions? As we thought about this situation and its possible solutions, it raised a few other questions: 1. Is it considered good design for two different classes to both provide read/write access to the same field in the database? 2. Does the use of a "SuperUser" account as described constitute a breech of security? 3. Is it possible for a situation to arise in which the system might not be able to discern the security context of a request to instantiate an object? If so, would it be acceptable to use a parameter to communicate that context? Thanks!
Perhaps a solution - although a slightly more complex one - would be to explictly set permissions on the user object, rather than the role. What i mean is, in Windows, any user can belong to groups and get some permission based on this group membership. However, you can also explicitly set a permission on the user to say, read a file. I'd think that in the plumbing, upon instantiation of the User (or perhaps Identity ) object, it is assigned permissions directly. So, I pseudo-code, on the constructor of your data class there should be something like: public myClass() { new DataAccessPermission(DataAccessPermission.Read)Demand(); // etc etc. } .... that permission demanding code should also be present in the properties of your class. What needs to be done for this though, is create your Permission sub-classes ( if an existing Permission class doesn't cover your requirements ), amd possible implement some "plumbing" inside them to access the permission you've set on the current user object. It's a bit tricky coding, but once you've got it, you've a perfect case of re-use for almost any project afterwards. I think it's worth taking the time, actually I was planning to create that sort of thing for the needs of my company as well in the near future, because we're gonna re-use it in almost any project that requires security. ( This is actually a Java-driven approach, but I think the 2 frameworks are more-or-less equivalent in functionality, so it shouldn't be very difficult to implement without any major difficulties ) Hope this helped, Angel O:] [quoted text, click to view] "craig" <e@mail.com> wrote in message news:eD2XGiIuEHA.2196@TK2MSFTNGP14.phx.gbl... > I am working on my first .NET development project that involves custom > role-based security per the project requirements. This lead to a general > design issue this week that really caused us some concern. I have described > the situation below because we are very curious to see what other, more > experienced, developers might suggest. The specific classes and fields are > used just to illustrate the concepts. > > Our application uses role-based authorization security. Thus, we allow the > administrator to define roles to which the can define various permissions. > Permissions are defined relative to the various entities in the application, > such as Users, Customers, Services, etc. One such role might be defined as > follows: > > Role: Administrator > Permissions: Add User, Delete User, View User, Update User > > Thus a user that is added to the Administrator role is granted permission to > add, delete, view and update User entities. Once such a user is > authenticated, they will be authorized to perform those actions. > > Now, consider that the User entity is abstracted by a User class, and > suppose that class has a Username field (among others). If an authenticated > user indicated that they would like to edit the Username field of a system > User entity, the system first checks to see what role the authenticated user > is in. If they are in an administrator role, they have the desired "Update > User" privilege described above, so the system instantiates a User object > and presents it to the user for editing. If, however, the user does not have > this permission, their request is denied and the system does not instantiate > an object. > > So far, so good. > > Now, suppose that another requirement is that ANY user that is logged into > the system must be granted permission to edit their own Username, regardless > of what role they are in. In otherwords, the currently authenticated user > should always be granted the ability edit their own Username. > > Now, here is where we ran into a problem. If the currently authenticated > user would like to update their Username field, but they are not in an > Administrator role, the system will not allow the User object to be > instantiated, so they will not be able to edit their Username as desired. > The object that provides the functionality needed is not accessible. As we > began to think about this situation, it was not clear how best to solve the > problem and it lead to quite a bit of discussion. Naturally, we wondered if > this is a common problem for which there is a consensus solution in the > developer community, or whether there was just something inherently wrong > with our role-based security model, our object model or our logic. > > Here are some of the solutions we considered. I was hoping to hear what > others think. > > 1. Create a hidden "System" role which has all possible permissions. Add a > hidden "System" user to this role. Anytime such a situation occurs, log out > the current user, log in the System user, perform the desired actions, then > log the current user back in. > > 2. Create a different class, with different security logic, that can be used > to expose the proper Username field to the currently authenticated user for > editing. This would mean that a single field in the DB would be editable > through two different classes. > > 3. Add additionaly security logic to the User class such that it functions > as follows: If the authenticated user requesting a User object has Update > User permission, instantiate the requesed User object. If the authenticated > user > does not have Update User permission, allow them the ability to instantiate > only the User entity that corresponds to themselves, and expose only the > Username field for editing (make all other fields read-only). > > Any thoughts on the problem in general or the possible solutions? As we > thought about this situation and its possible solutions, it raised a few > other questions: > > 1. Is it considered good design for two different classes to both provide > read/write access to the same field in the database? > > 2. Does the use of a "SuperUser" account as described constitute a breech of > security? > > 3. Is it possible for a situation to arise in which the system might not be > able to discern the security context of a request to instantiate an object? > If so, would it be acceptable to use a parameter to communicate that > context? > > Thanks! > >
Actually, I've just found something that might make your life much easier, and you can combine it with the previous post: String id1 = "Bob"; String role1 = null; PrincipalPermission PrincipalPerm1 = new PrincipalPermission(id1, role1); String id2 = null; String role2 = "Supervisor"; PrincipalPermission PrincipalPerm2 = new PrincipalPermission(id2, role2); (PrincipalPerm1.Union(PrincipalPerm2)).Demand(); The following code will demand that the current IPrincipal of the system is either user "Bob", or that the current IPrincipal is a "Supervisor" ... in that manner, you can specify that the user accessing your data class is either an Admin, or the user with the username specified by the class instance itself - the only disadvantage is that upon construction of the data object, you don't really know the username contained inside the instance you're loading without doing a "select" from the DB ... but, almost nothing is perfect, innit ? You get some small performance overhead, but great ease-of-use codewise O:] [quoted text, click to view] "Angelos Karantzalis" <akarantzalis@agiltech.gr> wrote in message news:#Ky7T0muEHA.3456@TK2MSFTNGP14.phx.gbl... > Perhaps a solution - although a slightly more complex one - would be to > explictly set permissions on the user object, rather than the role. What i > mean is, in Windows, any user can belong to groups and get some permission > based on this group membership. However, you can also explicitly set a > permission on the user to say, read a file. > > I'd think that in the plumbing, upon instantiation of the User (or perhaps > Identity ) object, it is assigned permissions directly. So, I pseudo-code, > on the constructor of your data class there should be something like: > > public myClass() { > new DataAccessPermission(DataAccessPermission.Read)Demand(); > // etc etc. > } > > ... that permission demanding code should also be present in the properties > of your class. > > What needs to be done for this though, is create your Permission sub-class es > ( if an existing Permission class doesn't cover your requirements ), amd > possible implement some "plumbing" inside them to access the permission > you've set on the current user object. It's a bit tricky coding, but once > you've got it, you've a perfect case of re-use for almost any project > afterwards. > > I think it's worth taking the time, actually I was planning to create that > sort of thing for the needs of my company as well in the near future, > because we're gonna re-use it in almost any project that requires security. > > ( This is actually a Java-driven approach, but I think the 2 frameworks are > more-or-less equivalent in functionality, so it shouldn't be very difficult > to implement without any major difficulties ) > > Hope this helped, > > Angel > O:] > > > "craig" <e@mail.com> wrote in message > news:eD2XGiIuEHA.2196@TK2MSFTNGP14.phx.gbl... > > I am working on my first .NET development project that involves custom > > role-based security per the project requirements. This lead to a general > > design issue this week that really caused us some concern. I have > described > > the situation below because we are very curious to see what other, more > > experienced, developers might suggest. The specific classes and fields are > > used just to illustrate the concepts. > > > > Our application uses role-based authorization security. Thus, we allow the > > administrator to define roles to which the can define various permissions. > > Permissions are defined relative to the various entities in the > application, > > such as Users, Customers, Services, etc. One such role might be defined as > > follows: > > > > Role: Administrator > > Permissions: Add User, Delete User, View User, Update User > > > > Thus a user that is added to the Administrator role is granted permission > to > > add, delete, view and update User entities. Once such a user is > > authenticated, they will be authorized to perform those actions. > > > > Now, consider that the User entity is abstracted by a User class, and > > suppose that class has a Username field (among others). If an > authenticated > > user indicated that they would like to edit the Username field of a system > > User entity, the system first checks to see what role the authenticated > user > > is in. If they are in an administrator role, they have the desired "Update > > User" privilege described above, so the system instantiates a User object > > and presents it to the user for editing. If, however, the user does not > have > > this permission, their request is denied and the system does not > instantiate > > an object. > > > > So far, so good. > > > > Now, suppose that another requirement is that ANY user that is logged into > > the system must be granted permission to edit their own Username, > regardless > > of what role they are in. In otherwords, the currently authenticated user > > should always be granted the ability edit their own Username. > > > > Now, here is where we ran into a problem. If the currently authenticated > > user would like to update their Username field, but they are not in an > > Administrator role, the system will not allow the User object to be > > instantiated, so they will not be able to edit their Username as desired. > > The object that provides the functionality needed is not accessible. As we > > began to think about this situation, it was not clear how best to solve > the > > problem and it lead to quite a bit of discussion. Naturally, we wondered > if > > this is a common problem for which there is a consensus solution in the > > developer community, or whether there was just something inherently wrong > > with our role-based security model, our object model or our logic. > > > > Here are some of the solutions we considered. I was hoping to hear what > > others think. > > > > 1. Create a hidden "System" role which has all possible permissions. Add a > > hidden "System" user to this role. Anytime such a situation occurs, log > out > > the current user, log in the System user, perform the desired actions, > then > > log the current user back in. > > > > 2. Create a different class, with different security logic, that can be > used > > to expose the proper Username field to the currently authenticated user > for > > editing. This would mean that a single field in the DB would be editable > > through two different classes. > > > > 3. Add additionaly security logic to the User class such that it functions > > as follows: If the authenticated user requesting a User object has Update > > User permission, instantiate the requesed User object. If the > authenticated > > user > > does not have Update User permission, allow them the ability to > instantiate > > only the User entity that corresponds to themselves, and expose only the
Thanks Angelos. I really appreciate your taking the time to respond. I will spend some time to study your posts. Looks like some good input. [quoted text, click to view] "Angelos Karantzalis" <akarantzalis@agiltech.gr> wrote in message news:eWr3R6muEHA.1420@TK2MSFTNGP10.phx.gbl... > Actually, I've just found something that might make your life much easier, > and you can combine it with the previous post: > > String id1 = "Bob"; > String role1 = null; > PrincipalPermission PrincipalPerm1 = new PrincipalPermission(id1, role1); > > String id2 = null; > String role2 = "Supervisor"; > PrincipalPermission PrincipalPerm2 = new PrincipalPermission(id2, role2); > > (PrincipalPerm1.Union(PrincipalPerm2)).Demand(); > > The following code will demand that the current IPrincipal of the system > is > either user "Bob", or that the current IPrincipal is a "Supervisor" ... in > that manner, you can specify that the user accessing your data class is > either an Admin, or the user with the username specified by the class > instance itself - the only disadvantage is that upon construction of the > data object, you don't really know the username contained inside the > instance you're loading without doing a "select" from the DB ... but, > almost > nothing is perfect, innit ? You get some small performance overhead, but > great ease-of-use codewise > > O:] > > > > > "Angelos Karantzalis" <akarantzalis@agiltech.gr> wrote in message > news:#Ky7T0muEHA.3456@TK2MSFTNGP14.phx.gbl... >> Perhaps a solution - although a slightly more complex one - would be to >> explictly set permissions on the user object, rather than the role. What >> i >> mean is, in Windows, any user can belong to groups and get some >> permission >> based on this group membership. However, you can also explicitly set a >> permission on the user to say, read a file. >> >> I'd think that in the plumbing, upon instantiation of the User (or >> perhaps >> Identity ) object, it is assigned permissions directly. So, I >> pseudo-code, >> on the constructor of your data class there should be something like: >> >> public myClass() { >> new DataAccessPermission(DataAccessPermission.Read)Demand(); >> // etc etc. >> } >> >> ... that permission demanding code should also be present in the > properties >> of your class. >> >> What needs to be done for this though, is create your Permission >> sub-class > es >> ( if an existing Permission class doesn't cover your requirements ), amd >> possible implement some "plumbing" inside them to access the permission >> you've set on the current user object. It's a bit tricky coding, but once >> you've got it, you've a perfect case of re-use for almost any project >> afterwards. >> >> I think it's worth taking the time, actually I was planning to create >> that >> sort of thing for the needs of my company as well in the near future, >> because we're gonna re-use it in almost any project that requires > security. >> >> ( This is actually a Java-driven approach, but I think the 2 frameworks > are >> more-or-less equivalent in functionality, so it shouldn't be very > difficult >> to implement without any major difficulties ) >> >> Hope this helped, >> >> Angel >> O:] >> >> >> "craig" <e@mail.com> wrote in message >> news:eD2XGiIuEHA.2196@TK2MSFTNGP14.phx.gbl... >> > I am working on my first .NET development project that involves custom >> > role-based security per the project requirements. This lead to a >> > general >> > design issue this week that really caused us some concern. I have >> described >> > the situation below because we are very curious to see what other, more >> > experienced, developers might suggest. The specific classes and fields > are >> > used just to illustrate the concepts. >> > >> > Our application uses role-based authorization security. Thus, we allow > the >> > administrator to define roles to which the can define various > permissions. >> > Permissions are defined relative to the various entities in the >> application, >> > such as Users, Customers, Services, etc. One such role might be defined > as >> > follows: >> > >> > Role: Administrator >> > Permissions: Add User, Delete User, View User, Update User >> > >> > Thus a user that is added to the Administrator role is granted > permission >> to >> > add, delete, view and update User entities. Once such a user is >> > authenticated, they will be authorized to perform those actions. >> > >> > Now, consider that the User entity is abstracted by a User class, and >> > suppose that class has a Username field (among others). If an >> authenticated >> > user indicated that they would like to edit the Username field of a > system >> > User entity, the system first checks to see what role the authenticated >> user >> > is in. If they are in an administrator role, they have the desired > "Update >> > User" privilege described above, so the system instantiates a User > object >> > and presents it to the user for editing. If, however, the user does not >> have >> > this permission, their request is denied and the system does not >> instantiate >> > an object. >> > >> > So far, so good. >> > >> > Now, suppose that another requirement is that ANY user that is logged > into >> > the system must be granted permission to edit their own Username, >> regardless >> > of what role they are in. In otherwords, the currently authenticated > user >> > should always be granted the ability edit their own Username. >> > >> > Now, here is where we ran into a problem. If the currently >> > authenticated >> > user would like to update their Username field, but they are not in an >> > Administrator role, the system will not allow the User object to be >> > instantiated, so they will not be able to edit their Username as > desired. >> > The object that provides the functionality needed is not accessible. As > we >> > began to think about this situation, it was not clear how best to solve >> the >> > problem and it lead to quite a bit of discussion. Naturally, we >> > wondered >> if >> > this is a common problem for which there is a consensus solution in the >> > developer community, or whether there was just something inherently > wrong >> > with our role-based security model, our object model or our logic. >> > >> > Here are some of the solutions we considered. I was hoping to hear what >> > others think. >> > >> > 1. Create a hidden "System" role which has all possible permissions. >> > Add > a >> > hidden "System" user to this role. Anytime such a situation occurs, log >> out >> > the current user, log in the System user, perform the desired actions, >> then >> > log the current user back in. >> > >> > 2. Create a different class, with different security logic, that can be >> used >> > to expose the proper Username field to the currently authenticated user >> for
Don't see what you're looking for? Try a search.
|