4
votes

I have an HR web application built in ASP.Net MVC split into areas, for example Manager, Employee. These areas represent different types of users in the system who are able to to different tasks. There is a legacy database involved and information for each user type is stored in a different table. Also, The the type of information stored for each user type is different so it makes sense that the tables are separate.

I am looking to implement claims based authentication for a couple reasons: One, it will be easier to store details about each user, on the client, such as username, roles etc. The other reason is that ClaimsPrincipal supports multiple Identities. This is important because in some cases a single person may need to access the system under multiple Identities at the same time. Eg. A Manager needs access to the system to perform administrative tasks, however the Manager also happens to be an Employee and should be able to log into the system as an Employee. Each area is treated separately, so that a even if a user is both a Manager and Employee they must log in separately to each area.

So here are my questions: Are multiple Identities through ClaimsPrincipal the way to go? Is there some other technique I am overlooking? If multiple Identities are the way to go, how do I log a user out of one area, but keep them logged in to another area if they happen to also be logged in to another area at the same time? Normally, to log out, the code would look something like this:

FederatedAuthentication.SessionAuthenticationModule.SignOut();

My assumption is that this will log the user out of both areas. Is this correct? Assuming that is the case, I thought I could simply remove the specific Identity from ClaimsPrincipal, then reset and write the SessionSecurityToken, but ClaimsPrincipal has no remove method, only AddIdentity. So I came up with the following pseudo code:

When logging out:

  • Count number of Identities in ClaimsPrincipal
  • If count == 1 log out as normal
  • If count > 1, since we cannot remove an identity, loop through the identities and create a new ClaimsPrincipal that excludes the identity we want to log out, then reset and write the SessionSecurityToken

Am I on the right track? Are there some good examples of how to implement multiple Identities in ClaimsPrincipal? I have searched and while I have found brief mention of multiple Identities, I have found no actual examples.

2

2 Answers

2
votes

Suggestion : In your particular case , we can have two ClaimsPrincipal objects dealing with two different ClaimsIdentity .

            var claims1 = new List<Claim>
            {
                new Claim(ClaimTypes.Name, "Louise")
               , new Claim(ClaimTypes.Role, "Manager")
            };
            ClaimsIdentity claimsIdentity1 = new ClaimsIdentity(claims1 ,"XYZ");
            ClaimsPrincipal principal1 = new ClaimsPrincipal(claimsIdentity1);

            var claims2 = new List<Claim>
            {
                new Claim(ClaimTypes.Name, "Louise")
               , new Claim(ClaimTypes.Role, "Employee")
            };
            ClaimsIdentity claimsIdentity2 = new ClaimsIdentity(claims2 ,"XYZ");
            ClaimsPrincipal principal2 = new ClaimsPrincipal(claimsIdentity2);
2
votes

It feels like your problem may be an artificial one:

Each area is treated separately, so that a even if a user is both a Manager and Employee they must log in separately to each area.

What is the requirement driving this separation? This is the crux of the problem and it is likely going to be easier to fix this than try to fudge a workable solution with multiple identities for a single user.


To answer your direct question, no, you cannot remove an identity from a principal. You can only create a new principal and replace the existing one with whatever set of claims you require.

Thread.CurrentPrincipal = new ClaimsPrincipal(...);

If you build the principal from the identities or claims of the existing principal, you can filter out the ones you want to remove.


Fundamental to claim-based authentication is the idea of separating the mechanism for authentication from the mechanisms for authorisation. You authenticate when you need to know the identity of the user. When you authorize you use the claims associated with the user to perform an access-control decision, such as letting them into a management area of your system.

The identity of the user should be who they are in the context of the system. In most systems, the user will have a single identity. It can be useful to have multiple identities for technical reasons, such as systems which allow the user to associate a single authentication with multiple, changeable identities, but generally a system is simplest if you have a single identity for each user, because the reality is that you have single user who typically presents a single identity to you.

I can only think of one legitimate reason for a user to log into a system with multiple identities: the user wants to operate using multiple identities to separate their activities, e.g. a work account and a personal account.

Your system should be able to operate with a single authenticated identity. If your managers need to go through an additional authentication step to reach the management section, don't try and remove their existing identity - instead perform authentication with elevating system and add the identity to their existing principal. The user has not changed, you have just gained more claims associated with them.