Skip to main content
Solved

Cloud Firestore Security Rules: Conditional Access Based On Subscription Status

  • November 20, 2023
  • 7 replies
  • 238 views

Forum|alt.badge.img+8

Hello,

Unfortunately documentation page https://www.revenuecat.com/docs/firebase-integration provides only client-side authorization check
 

getAuth().currentUser.getIdTokenResult()
  .then((idTokenResult) => {
     // Confirm the user has a premium entitlement.
     if (!!idTokenResult.claims.activeEntitlements.includes("premium")) {
       // Show premium UI.
       showPremiumUI();
     } else {
       // Show regular user UI.
       showFreeUI();
     }
  })
  .catch((error) => {
    console.log(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 ;)

Best answer by Bamba

Hello,
 

It really seems RevenueCat hired some people to write docs and support this forum who have no idea on SDKs internals; they can only refer to documentation, and in this specific case there is no any, it is not documented.

 

Here is what works with Firebase Cloud Firestore + RevenueCat Extension, just a template/example:

 match /aaa/{bbb}{
  	  allow read: if true;
      match /ccc/{ddd=**} {
        allow read: if request.auth.token.revenueCatEntitlements[0] == 'premium';
      }
}

 

This is just basic example; in RevenueCat, I have single product with “premium” identifier; in App Store, corresponding product is monthly subscription.

You need debugger & hacker skills to find that.

View original
Did this post help you find an answer to your question?
This post has been closed for comments

7 replies

Forum|alt.badge.img+8
  • Author
  • Helper
  • 27 replies
  • November 20, 2023

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


Ryan Glanz
RevenueCat Staff
Forum|alt.badge.img+8
  • RevenueCat Staff
  • 383 replies
  • November 22, 2023

Hi!

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.


Forum|alt.badge.img+8
  • Author
  • Helper
  • 27 replies
  • November 22, 2023

Thanks @Ryan Glanz 

I believe I found answer to my question after analyzing source codes of RevenueCat extension for Firebase at https://github.com/RevenueCat/firestore-revenuecat-purchases

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 ;)
Thanks,


Forum|alt.badge.img+8
  • Author
  • Helper
  • 27 replies
  • March 29, 2024
Ryan Glanz wrote:

Hi!

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.


Hello RevenueCat team,

Could you please provide few Firebase Cloud Firestore security rules examples, using “claims” (assuming Firestore uses RevenueCat extension).

Thanks,


Forum|alt.badge.img+8
  • Author
  • Helper
  • 27 replies
  • Answer
  • March 29, 2024

Hello,
 

It really seems RevenueCat hired some people to write docs and support this forum who have no idea on SDKs internals; they can only refer to documentation, and in this specific case there is no any, it is not documented.

 

Here is what works with Firebase Cloud Firestore + RevenueCat Extension, just a template/example:

 match /aaa/{bbb}{
  	  allow read: if true;
      match /ccc/{ddd=**} {
        allow read: if request.auth.token.revenueCatEntitlements[0] == 'premium';
      }
}

 

This is just basic example; in RevenueCat, I have single product with “premium” identifier; in App Store, corresponding product is monthly subscription.

You need debugger & hacker skills to find that.


Thanks for sharing Bamba. I think it just boils down to being familiar with the Security Rules syntax. Not everyone uses them


Forum|alt.badge.img+2

```
match /databases/{database}/documents {
      function hasProSubs() {
      return "pro" in request.auth.token.revenueCatEntitlements;
    }
```

Better to use “in” to handle mutliple subscriptions guys.

Be aware that claims are updated by RevenueCat with some latency compare of Firestore collection update. Which can result to scenario where your user has a subscription but when fetching a collection he got blocked by the security rule (even if you call getIdTokenResult(true))


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings