firebasegoogle-cloud-firestoregoogle-cloud-identity

Firestore Rules with multi-tenancy?


The Firebase Rules docs suggest building conditions comparing the authenticated user's token (i.e., request.auth) with the target Firestore document(s). Something like:

match /posts/{postId} {
  allow read, write: if (request.auth.uid != null) && 
    (resource.data.tenantId == request.auth.token.tenantId);
}

However, tenantId doesn't appear to be available in Firebase Rules like other related auth fields (e.g., uid, email, email_verified, etc.).

One option appears to be to add tenantId separately as a custom claim using the firebase-admin SDK. But that would create duplicate info on the user object:

{
  uid: 'nzjNp3QIfSR6uWy',
  emailVerified: true,
  displayName: 'pickleR'
  ...
  tenantId: 'wubalubadubdub',
  customClaims: { tenantId: 'wubalubadubdub' },
}

An alternative option appears to be to create a tenants collection in Firestore. However, that approach seems to introduce needless complexity and inflate the # of required Firestore queries.

Are there alternatives for accessing the tenantId in Firestore Rules and/or alternative best practices for using Firestore with multi-tenancy?


Solution

  • The two options you describe are the idiomatic ones:

    1. Pass the information into the rules as part of the ID token as a custom claim.
    2. Look up the information in the database from the rules by the request.auth.uid.

    Neither of these is always better than the other: custom claims are more convenient and readable, while using the database is usually faster. It's common to use the database lookup for more volatile information, and claims for information that is "once".

    Since this is for a tenant ID, which is unlikely to change quickly, I'd probably go for a custom claim.