Multitenancy refers to a principle in software architecture where a single instance of the software runs on a server, serving multiple client-organizations (tenants)
Let's start by enumerating some multi tenant applications and understand how they handle it.
- Slack implements a login screen asking for email. Based on the email it will redirect to https://{account}.slack.com
- Slack must be storing the mapping between email (or email suffix) and subdomain. Notice that when I enter matias@auth0.com I get redirected to my own domain
- Right now they only support email/password. But they plan to support enterprise SSO. This login experience where they ask email first for sure is in preparation to support enterprise SSO. Each organization will have configured its identity provider (SAML, ADFS, etc.) and Slack will redirect there once the user entered their email.
- You can belong to multiple teams (or organizations) in Slack. Each team/org can be considered a tenant.
- You can switch from one team to another through an option in Slack
- Users can be either full access or single-channel access within a team (organization)
- A user can be have full access on one team but single-channel access on another
{
email: 'matias@auth0.com'
permissions: [
"auth0":
{
role: "admin",
channels: ["*"]
},
"another-company":
{
role: "single-channel",
channels: [ "some-channel" ]
}
]
}
Authentication:
- Dropbox asks for an e-mail. Based on the e-mail suffix, if there is an organization with a domain that matches that suffix, it will hide the password and show "Single Sign On Enabled". When the user clicks on the "Continue" it will be redirected to the identity provider. If there is no SSO configured for that domain, the user will just enter the password.
Authorization:
- Once a user is authenticated you get access to folders/files you own and folders you were shared.
- You get access to your personal account and any organization you belong
{
email: 'foo@bar.com'
permissions: [
"personal":
{
role: "full",
},
"company1":
{
role: "user",
},
"company2":
{
role: "admin",
}
]
}
Storing the folders you have access to as part of the user model in this case, would be overkill. The user object can get really big if you have lots of folders. Instead storing up to company level role and then the rest would be handled on the application/db level.
Authentication:
- Auth0 has a single dashboard for all the tenants and it is accesible through https://app.auth0.com.
- It supports Google, GitHub, Live and User/Passwords.
- It also supports Enterprise connections (configured manually for now) and using the email domain for home realm discovery (see screen below). Similar to Dropbox experience.
Authorization:
- A user can belong to multiple tenants and have different permissions on each tenant (user foo can be an admin on tenant bar and be a regular user of tenant xyz.
- It is implemented by assigning the
user_id
property to an "account-level" entity together with the permission if the user has access to everything OR to an "app-level" entity if the user has an app level permission.
{
email: 'foo@bar.com'
permissions: [
"company1":
{
role: "full",
clients: [ "*" ]
},
"company2":
{
role: "app-owner",
clients: [ "iaeonoemaoiy2ie029je" ]
}
]
}
Here is a typical scenario of a SaaS multi tenant app:
-
- Many clients signup with a custom username/password. Especially during trial periods.
-
- Some customers login with their existing Google, LinkedIn & Yahoo! credentials.
-
- Small businesses with employees directories based on Office365 or Google Apps have a preference for login using these credentials.
-
- Bigger companies often have already one or many identity systems for employees. Many rely on Active Directory, or LDAP. Some have deployed systems for identity federation based on ADFS, PingFederate, Okta, OneLogin, CA Siteminder, or even custom SAML-P providers.
The app is primarily a web app, built as a Single Page App (SPA) using AngularJS with a backend API built with nodejs. They also have a mobile app for Android and iOS with a subset of the web app functionality.
Typically you would be ok with just one database connection. Whether the user has access to a certain tenant or not should be handled with metadata, not with different database connections. The only case where it would make sense to use different db connections is if you need to isolate a set of users (e.g. staging vs prod environment), but even then we would recommend creating different accounts in Auth0 for that case. The other case where you would need a separate database connection would be if "tenant-A" use the builtin Auth0 user store but "tenant-B" has a set of users somewhere and you want to authenticate those users. In that case you would create a custom db connection only for that tenant and somewhere in your application you would have to store that association.
Typically yes, one account per tenant would be ok and it would allow you to manage everything from the same place. The only case in which it would make sense to have a new Auth0 account per tenant, would be if you want to give access to that tenant to the Auth0 dashboard. Notice that if you do that you would have to leverage the API to create a new account, application and connections programatically. If you need access to such API send an email to support@auth0.com
As explained above, the way to handle roles per tenant would be using metadata.
Here is an example that would model a simplified "Slack" (a chat application) authorization model.
{
email: "matias@auth0.com"
permissions: [
"auth0":
{
role: "admin",
channels: ["*"]
},
"another-company":
{
role: "single-channel",
channels: [ "some-channel" ]
}
]
}