Setting Up A Multi-Tenant Application With Firebase, GraphQL, and Angular

Share on facebook
Share on google
Share on twitter
Share on linkedin

In this post, I will show you, how to set up a multi-tenant application with Firebase, GraphQL, and Angular. This is a common scenario for SaaS applications, as multiple tenants should be able to have their data separated from other tenants’ data and that data should be kept safe as well using proper authorization checks.

We will cover, how to design the Firebase Firestore database and setup Firebase Authentication to support multiple tenants as well as how to implement the necessary authorization checks on a GraphQL NodeJS server hosted with Firebase functions. There is going to be an Angular app, containing the course portal, which among others, are used for Angular Architect Accelerator.

Design the Firestore database

First, we are going to design our Firestore database to support multiple tenants. We are going to do this, by creating a schools collection, containing the different schools (tenants). The tenant’s data are then nested under these schools, that way the tenant’s data is split among separate vertical slices, which makes the security and tenant management easier.

Under each school (tenant), the tenant data is users (containing user-specific data), and course collection. Each course includes sections, lessons, and resources collections (containing the necessary data for each school).

On the top level, the schools collection contains the tenants, which contains courses and users:

 

 

Each course contains sections, resources, and lessons, where the sections contain a list of referenced lessons:

We store user data such as completed lessons and action items on each users’ entry:

 

 

 

Having that set up, our database now supports multiple-tenants, as well as user and course-specific data for each tenant.

Activating multi-tenant login

To support multi-tenant authentication we will use Firebase Authentication + Google Cloud Platforms’ Identity Platform, which will provide us with multi-tenant support.

You will need to go to Identity Platform in Google Cloud Platform and enable it. Here you can create tenants and add users to a specific tenant.

Integrating with the GraphQL server

We need to do these things in the GraphQL server:

  1. Verify id token on the requester and setting role and tenant id to each resolver, so we have it handy for all resolvers
  2. Use the tenants when reading and writing from/to Firestore

Verify id token and set context

For convenience, we want to get the schoolId from an HTTP header, we are setting in our GraphQL context, so we can access it in every query/mutation without the client needing to provide it explicitly in the GrahQL payload.
Also, we want to get the user id and validate, that the requesting user has a valid token. We are using Firebase Authentication for authentication on the Angular client.

We set this data, as well as verifies the id token in the Apollo server context middleware (on our GraphQL NodeJS server):

Use the context in the resolvers

In the queries and mutations, we want to check, that the uid in a payload, matches the current user’s userid (which we get from context) or the user is an admin of that user’s school.

Here we are using the context data to check if the requesting user is authorized to update the lesson’s completed status and is using the schoolId (tenantId) to update Firestore.

Setting up the clients for multi-tenancy

Since the clients need to tell the server on each request, which school it belongs to, it is convenient to do that using a header in an HTTP interceptor.

In this snippet, the schoolId and idToken is set as HTTP headers on each request and is used in the Apollo context as shown in the previous section.

Clients routing flow

For the routing, we need the route to start with the schoolId param, so we can set the school id.

The SchoolIdResolver is setting the Firebase Authentication tenant id:

After the user is logged in, it is navigated to a page for selecting the course:

Conclusion

What’s it! Now multiple tenants can use your application and have their data nicely separated and secured on your backend. Also, we saw how to make it simple for the clients to provide the tenant identifier (schoolId) to the server on each request, as well as having the routing set up for multi-tenancy.

Do you want to become an Angular architect? Check out Angular Architect Accelerator.

Hi there!

I’m Christian, a freelance software developer helping people with Angular development. If you like my posts, make sure to follow me on Twitter.

Related Posts and Comments