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.

Related Posts and Comments

Supabase and Angular: A Powerful Combination for Building Web Applications

Supabase is a cloud-based backend as a service (BaaS) platform that provides developers with a set of tools and services for building scalable and secure web applications.It’s much like Firebase but Supabase provides a PostgreSQL database which solves some of the inconveniences with a NoSQL database such as Firestore.For that reason, Supabase has now become

Read More »

Walkthrough: Building An Angular App Using Tailwind CSS and Nx

In this video, we will cover a walk-through from scratch covering how to Build and Angular app using Tailwind CSS and Nx including Angular standalone components. 🖌 Tailwind CSS setup and usage⚙️ Nx monorepo configuration🧍‍♂️ Standalone components✅ Building a complete app in less than 2 hours with best practices ⏳ Timestamps:0:00 – Intro1:00 – Tailwind

Read More »

18 Performance Optimization Techniques For Angular Applications (podcast with Michael Hladky)

Performance is extremely important in front-end applications as they directly impact the application’s user experience. Poorly performing applications can be frustrating for the end-users. For example, an e-commerce site that is slow and unresponsive might deter users which could have a direct impact on the business.  Although there is a growing number of tools to

Read More »

Announcement: Angular Testing Workshop

I’m announcing a new live workshop: Angular Testing Workshop. It will be half-day workshops over three days, 100% online, where we will learn all the industry best practices with Angular testing so you can apply them in your daily work – taking straight out of my experience with doing Angular testing for big projects. The

Read More »