C
craig
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!
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!