0

Let's assume that I have a multi-tenant .NET application where each tenant hold their own users. When a request comes to my web server, I need to first determine the tenant. Later, I will try to authenticate the user based the information passed through the HTTP headers. At this point, I actually have two identities: one for the tenant and the other for the user. The below code explains the intention of what I want to do:

class Program
{
    static void Main(string[] args)
    {
        // NOTE: The below is a sample of how we may construct a ClaimsPrincipal instance over two ClaimsIdentity instances:
        //       one for the tenant identity and the the other for the user idenetity. When a request come to the web server, we can determine the
        //       tenant's identity at the very early stages of the request lifecycle. Then, we can try to authenticate the user based on the 
        //       information passed through the request headers (this could be bearer token, basic auth, etc.).

        const string authServerName = "urn:myauthserver";
        const string tenantAuthType = "Application";
        const string userAuthType = "External";

        const string tenantId = "f35fe69d-7aef-4f1a-b645-0de4176cd441";
        const string tenantName = "bigcompany";
        IEnumerable<Claim> tenantClaims = new Claim[]
        {
            new Claim(ClaimTypes.NameIdentifier, tenantId, ClaimValueTypes.String, authServerName),
            new Claim(ClaimTypes.Name, tenantName, ClaimValueTypes.String, authServerName)
        };

        const string userId = "d4903f71-ca06-4671-a3df-14f7e02a0008";
        const string userName = "tugberk";
        const string twitterToken = "30807826f0d74ed29d69368ea5faee2638b0e931566b4e4092c1aca9b4db04fe";
        const string facebookToken = "35037356a183470691504cd163ce2f835419978ed81c4b7781ae3bbefdea176a";
        IEnumerable<Claim> userClaims = new Claim[]
        {
            new Claim(ClaimTypes.NameIdentifier, userId, ClaimValueTypes.String, authServerName),
            new Claim(ClaimTypes.Name, userName, ClaimValueTypes.String, authServerName),
            new Claim("token", twitterToken, ClaimValueTypes.String, authServerName, "Twitter"),
            new Claim("token", facebookToken, ClaimValueTypes.String, authServerName, "Facebook")
        };

        ClaimsIdentity tenantIdentity = new ClaimsIdentity(tenantClaims, tenantAuthType, ClaimTypes.Name, ClaimTypes.Role);
        ClaimsIdentity userIdentity = new ClaimsIdentity(userClaims, userAuthType, ClaimTypes.Name, ClaimTypes.Role);

        ClaimsPrincipal principal = new ClaimsPrincipal(new[] { tenantIdentity, userIdentity });
    }
}

What I am doing here is to create a ClaimsPrincipal instance based on two ClaimsIdentity instances. For a multi-tenant application, is this the right way to handle tenant and user identities in a .NET server application?

tugberk
  • 57,477
  • 67
  • 243
  • 335

1 Answers1

0

I would stick with a single identity with additional claims that allow you to identify the tenant. This is how we always do it.

This way you can verify whether a user tries to switch to another tenant and either reauthenticate (issue a new claim set) or disallow the access.

Wiktor Zychla
  • 47,367
  • 6
  • 74
  • 106
  • Thx. `This way you can verify whether a user tries to switch to another tenant`: this's not a case. The each tenant has its own user identity management inside its separate data storage system. – tugberk Nov 04 '14 at 13:14