Multi-Tenant SaaS application user management with Auth0

Manish Mehta
7 min readSep 5, 2021

--

For Microservice Architecture

and keep developers happy……..

When it comes to building multi-tenant applications, managing tenants(customers) with their authentication/authorization becomes one of the most critical and demanding tasks.

Recently we at Betsol for one of our major SaaS application were looking for a solution provider which can help us manage our tenant's login and their user data while keeping the below requirements in mind:

  1. Support for both B2B and B2C customers
    We needed a solution that can allow us to manage both B2C(customers for personal usage) and B2B(all sizes of business customers) i.e it should also support SSO logins for enterprise customers with protocols like SAML and OpenID Connect etc.
  2. Tenant data Isolation
    For a multi-tenant system, it's a top priority task to isolate data of one tenant from another while providing the optimum performance and for this Auth0 Organizations came into the picture.
  3. Role-Based Access Control(RBAC)
    Having a user management solution without access control sounds inappropriate right! but what if you don't have a granular level control or option to provide custom roles/permissions but don't worry Auth0 Roles/Permission to the rescue.
  4. Pricing
    Before selecting any solution, the pricing of the product decides whether to go ahead or look for some other product and that’s why check the pricing of Auth0 here. We are in talks with them for pricing and if it doesn’t go as expected then other options…..
    Also, it provides a free account with rich features along with unlimited logins.
  5. Ease of Integration
    This point is totally coming from a developer’s perspective and doesn't look very important but it is one of the key driving forces for an efficient development process to integrate the solution with your application. When it comes to Auth0 I can definitely vouch for its development integration.

Considering above requirements and few others like data residency and regional compliance etc in mind, We looked for many solutions like Azure AD, AWS Cognito, Okta etc but couldn’t get satisfied with all the points and finally went with Auth0 and successfully built a POC for our microservice based SaaS application. Also this was just for POC and to demonstrate Auth0 can be used for user management but implementation can be changed according to the needs.

Intended Application Architecture

Our implementation having authentication/authorization at the service level

Tech Stack:
React Frontend with Node(ExpressJS) for user management(auth Service), node(FastifyJS) for another service(in the architecture diagram above), and currently working on another service with Golang(Gin).

The Implementation

Initial Setup

  1. Register a SPA in Auth0
    Create a react app in Auth0 which acts as the medium between your application and Auth0 from which the user will log in. After completing the next step(2. API creation) add the audience URL in the SDK as mentioned below.
  2. Register an API in Auth0
    Create an API in Auth0 and add permissions so that when a user accesses the APIs with an access token(JWT) you can verify if the permission is present or not. Make sure when you log a user in, you always provide the audience URI to the react SDK to get a JWT from Auth0 that is valid for that particular audience and the same will be used in API authentication(checkJwt middleware defined in the linked document).
  3. Add Authorization in the API
    To verify if authorization is working properly, create an admin role in Auth0 and assign “read:messages permission to the admin role and after signup/creating a new user, add the role to that user and then re-login and then access the “/api/private-scoped” API(created in step 2) with the JWT and you should get a 200 response while a user with no permission will get 403 response.
    Note: By default express-jwt-authz package checks the “scope” property of JWT to get the permissions and Auth0 sends the permission in a separate “permissions” claim(property) so you need to update a line mentioned below:
const checkScopes = jwtAuthz([ 'read:messages' ]);with the below line having option for custom scope key:const checkScopes = jwtAuthz([ 'read:messages' ], { customScopeKey: "permissions" });

Multi-tenant B2B solution

For managing a business tenant you need to create an Organization in Auth0, for example, your client is Netflix so you need to create an organization in Auth0 named Netflix which will manage all the users in it along with their own SSO(SAML, etc) log in if they want to.

Important: While logging a user in for any particular organization in Auth0 you need to provide an organization prop in Auth0 component having organization id as its value, this is required because Auth0 separate organizational context and normal login. It also means when a user logs in with organization context the Roles to the user will be different than the global roles assigned to that user, i.e a user can be an admin in Auth0 users but might be a normal user as an organization member. Check here to assign roles to organization members.

For allowing users to login in the organization context we need to have an organization id first, for that also Auth0 provides a feature called Organization Prompt, if turned on in your application, will ask the user to enter organization name before login but your app will be restricted to allow only B2B(organization) user’s login and also won't be a great user experience. Apart from organization id, a connection id is also needed to login to a particular organization and that connection should be enabled for that organization, check about connections here. We will also allow creating SSO(SAML) login for our tenants with their own ID providers later and for that an enterprise connection on Auth0 will be created. Remember that on Auth0 a default Database connection will be present and is used for all logins until another connection is created and specified in login explicitly.

How We Did It
Whatever you do on the Auth0 dashboard can be done using their Management APIs and for providing a seamless UX we used these APIs instead of asking a user to enter/select organization name/id we just asked their email address.

Let's begin with the signup flow:
1. User signup to your app via Auth0 React SDK.
2. Next step is to take the user's organization name(this step is mandatory and cannot be skipped since the POC was only intended for B2B tenant).
3. Create an organization with the name provided in the previous step on Auth0.
4. Add current user to that organization.
5. Assign admin role to the above user in the organization, we stored the admin role id in our environment variable for this purpose.
6. Now the onboarding process for the user of an Organization is done. Return the organization id in the API response.
7. Relogin user in Organization context by providing the organization id in the getTokenWithPopup function as
{organization: “org_id_returned_from_your_API” }
8. Relogin above will happen silently with a pop-up and you will get all the permissions of admin in the JWT for the organization context.

Photo by bruce mars on Unsplash

Finally, we are done with the Signup flow and now you are logged in as an admin of your Organization, Now you can perform any operation like inviting other users from your company to make them members of your organization in the SaaS application or create an SSO(SAML) connection for your organization for removing the need of passwords; But before doing any of that stuff lets check how we implemented Login Flow without organization id input from the tenant.

Login flow:
1. Take user email from a form on UI, and on your back-end fetch user detail from Auth0.
2. From user-id fetched in step 1 get the user’s organization.
3. Now get the user organization’s connections and filter out SAML connection if present and return to the react client.
4. That's it, you got both organization id and connection id to log a user in for his/her organization context via the Auth0 React SDK.

Admin Operations

  1. Create SSO(SAML) Connection:
    Follow this document to create a SAML connection and then add(enable) it in your Organization.
    Now do the same process from the below Management APIs:
    a. Create Connection.
    b.
    Add Connection to Organization.

On UI take SSO URL and Signing Certificate from the user(tenant) who will get this info from their Id provider in our case we created an Okta developer account and then added a SAML application for Auth0 integration.

2. Invite members in your Organization:
Follow this document to invite members in your organization while selecting role ids(get roles via this API) and the connection(get connection via this API) from which they need to signup.

When you send an invitation, an email is sent from Auth0 with an invitation/signup link to the user, and that link contains an API which you need to provide in your application setting and also you need to create that API(must be an HTTPS endpoint) which should redirect the invitation parameters to the /authorize endpoint for your Auth0 account, please check the details here.

Conclusion

In my personal experience, the Auth0 platform felt great in terms of development and provides a rich set of features with ease of integration.
Currently, we are using GitLab’s CI/CD to deploy our application on GCP(Google Kubernetes Engine) with 2 microservices handling authentication/authorization on the service level and also we are using Auth0 organization’s metadata to store our tenant's info i.e customer Id for the other service to get details of the user from the auth service and communication between the service also requires the access tokens(JWT).

Although I have praised Auth0 so much but remember its pricing is relatively higher than any other ID provider solution as it has fixed pricing(no free MAU tier) for all users according to the subscription you are buying.

I have explained everything in detail but if you still have a doubt or confusion, you are welcome to drop your query in the comments. PS this is my first article!

--

--

Manish Mehta
Manish Mehta

Written by Manish Mehta

An Engineer taking the help of computers and logical reasoning to solve real-world problems. More Info : www.manish-mehta.in/?s=m

Responses (1)