Lately I have been looking a bit closer at the existing options for designing and building multitenant applications in ASP.NET Core and I just wanted to share a some of my thoughts on this.
If you have some experience building multitenant applications you would agree that this is no small task, there are many things you have to think about and design for, but mainly the one common factor that comes to mind when dealing with multitenancy is 'tenant isolation'. That is, every tenant in your application has to be guaranteed complete isolation for data access, resource access and sometimes even physical access such as completely separate databases. In essence, security and data isolation are amongst your top concerns when dealing with multitenant applications.
Let's take a quick peek at the options available for addressing some of these concerns.
I have been delving a bit deeper into the multitenant Azure AD sample application provided by Microsoft: Build a multi-tenant SaaS web application that calls a web API using Azure AD The sample provides starting guidance on how to setup a multitenant application in Azure AD, and it also shows how to federate such application with a another domain (tenant) outside of the domain where the application was first registered. This is a good starting point, since Azure AD's directories are indeed completely separate domains with their own users, groups and permissions. Thus, Azure AD offers secure domain isolation out of the box. What is more, the secure foundation of Azure AD can be leveraged to sync tenant information in the data store of your choice during the sign up process.
So I went ahead and setup two active directory instances in Azure AD, one for 'JLA Infinity' and one for 'Avengers Apocalypse'. These two fictitious domain directories contain its own set of users and are completely isolated from each other, in other words they are in completely different 'universes'. However, as life would have it, these two different universes would need to talk to each other in order to accomplish a common goal, thus 'JLA Infinity' will allow 'Avengers Apocalypse' to access their multitenant application through federated means.
Here is the list of 'JLA Infinity' Tenants:
And this is the list of the 'Avengers Apocalypse' tenants:
Note: I (Juan Pablo 'JP' Velasco) exist in both domains (universes) since I am the sole creator of both domain instances (parallel universes), but I digress... :)
So now Bruce Wayne, who is the global domain administrator for the 'JLA Infinity' universe, can sign up all of the rest of the users in his domain by checking that option and consenting access in a couple of simple pages:
The advantage of having Batman...ahem, Bruce sign up all of the 'JLA Infinity' users, is that now all of the standard users in that domain just have to sign in without having to allow any further consents to the application. On the other hand, Tony Stark is the global admin for 'Avengers Apocalypse' domain:
Therefore, when Tony signs up for the application and gives his administrative consent, he is also automatically signing up the rest of his friends along with him:
So now both users, Tony and Bruce, can be logged into the same application offered by 'JLA Infinity' and are provisioned with their own account via their respective tenant while leveraging Azure AD:
Also, Tony can view some of the claims for his account that are now available in the application:
Azure AD provides some powerful functionality for creating secure multi tenant applications, and the fact that this feature integrates with ASP.NET Core is a major plus.
Microsoft provides a nice set of database tools for working with Azure SQL database, which provides a nice way to scale out your workload. You can find more about the Elastic Database tools here: Scaling out with Azure SQL Database
Now, you don't necessarily need these tools in order to create a multi tenant database, however, the tools do provide some needed abstractions around 'sharding', that is the ability to partition one Azure SQL Database or 'shard' with multiple 'shardlets'. For more information on all the terms used by the Elastic Database tools head over to here: Elastic Database tools glossary Given that multiple tenants may be accessing the same database, their data paths should never cross. And there are many options for this type of data isolation, including the provision of tenants with their own database. The Elastic Database tools provide the means to move different 'shardlets', that is the data belonging to a specific tenant, across databases or 'shards'. This is useful not just for data isolation, but also for data storage management, as the needs for data storage for different tenants grow at different rates the tools allow for ease of migration to allow for continued growth. But this is just the tip of the iceberg, and I am not a data expert, so take this with a grain of salt. Nevertheless, data storage, data migration, data archival and retention policies, data encryption and security, data load balancing and any other data related activities should be on top of your list when designing your next multitenant application.
Now for the not so good news, these Elastic Database tools are not yet available for ASP.NET Core or Entity Framework Core (if an ORM is what you need) consumption:
First class support for Elastic DB
Yet there is hope, since the projects are open source it looks like some great folks in the developer community are helping to bring this functionality to Entity Framework Core:
Support for .net Core and EF core?
However, ideally Microsoft will eventually merge or add these efforts into their own roadmap and fully support these tools in the new world of .NET Core.
I briefly touched on just some of the considerations that are needed to design and create multi tenant applications in ASP.NET Core. It is still early in the release process (1.0 just came out) to assume that all of the needed tools and libraries exist today to support a fully functional multitenant application using a cross platform paradigm. However, the tooling will get better as will the support for the different libraries. Just like in the early .NET Framework 1.x days, the whole story was not written yet. And fast forward to today and we have generics and lambdas amongst many other things in the languages and frameworks that we now take for granted. In time I believe the .NET Core story will start to solidify, and I am truly eager to watch that story unfold in the years to come.
Until next time, live long and prosper. :)