Cloud Firestore Security Rules: Conditional Access Based On Subscription Status

  • 20 November 2023
  • 3 replies

Badge +1


Unfortunately documentation page provides only client-side authorization check

.then((idTokenResult) => {
// Confirm the user has a premium entitlement.
if (!!"premium")) {
// Show premium UI.
} else {
// Show regular user UI.
.catch((error) => {


It won’t prevent me to write code accessing Firestore with expired subscription. 

Can you please provide some examples / design patterns / best practices for server side? For example, Cloud Firestore Rules which check subscription status, or maybe cloud functions? Hard to guess ;)

3 replies

Badge +1

Maybe as simple as this?

service cloud.firestore {
match /databases/{database}/documents {
match /articles/{articleId} {
allow read: if true;
allow write: ....;

match /protected/{protecedId} {
allow read: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.subscription == true;

And cloud function listening for updates from Apple/Google stores?

Any better examples? I was expecting that RevenueCat Firebase Integration provides “out-of-the-box” server-side API which we can use to customize Cloud Firestore Security Rules

Userlevel 3
Badge +8


We’re unable to give specific cloud function examples, but many developers will simply call our GET /subscribers api endpoint from firebase if they want to check subscription status away from the client.

Badge +1

Thanks @Ryan Glanz 

I believe I found answer to my question after analyzing source codes of RevenueCat extension for Firebase at

The code will listen to App/Google/Amazon store events and apply custom claims to “user” entity in Firebase, so that I only need to configure Cloud Firestore Security Rules with these *undocumented* claims; I can only guess that if my subscription is called “premium” in RevenueCat then Firebase Rule will be something like

"rules": {
"adminContent": {
".read": "auth.token.premium === true",
".write": "auth.token.premium === true",

And after that client-side handles it (as in example in 1st post here)

Would be nice to have more examples for newbies like me ;)