[Discussion] Disable all mutations not originating from Cloud Functions

Hi, I want to raise a discussion around a topic that I’ve thought about for a while but never discussed with others using Parse.

We’ve got a fairly large application powered by Parse, ~100 classes with roughly ~300m objects in total. We’ve got a couple of clients calling this application, 2 web apps (React) and 2 native apps (React Native). A couple of years ago we realized that mutating objects on each client had a couple of issues.

  • If you want to mutate multiple objects from multiple classes you’re more exposed to network errors that could result in an inconsistent state.
  • It’s painful to maintain duplicated mutation logic between the clients (since they are all running JavaScript this could be done with a shared lib though).
  • It’s hard to keep track of all the different mutations that are spread among the clients.
  • An authenticated user could in theory corrupt their data by just making requests towards the API, which is far from ideal.

For these reasons we moved all our mutations to be encapsulated in Cloud Functions instead. Since we didn’t want the clients to be able to perform unintended mutations we have basically all our CLPs set to read only (we still perform queries in the clients).

This however causes a quite heavy use of “useMasterKey” for mutations. We still authenticate each cloud function based on roles and object ownership etc, but this increases the risk of unintentionally exposing objects that the calling user shouldn’t have access to. This really comes down to the fact that instead of just using the CLP we have to maintain the security for each Cloud Function which is more prone to dev errors.

A solution to this would be to basically disable all mutations that doesn’t originate from Cloud Functions so we can updated our CLPs to include write permissions which would enable us to use “sessionToken” instead of “useMasterKey”.

What’s your thoughts on this? Does it sound crazy or have to also felt the need to channel all your mutations via Cloud Functions?

All the best,

I got your points and I believe your idea makes sense. Unfortunately there is no built-in function for that. But I believe that you could perhaps add an Express.js custom middleware before Parse and block requests to the classes endpoints.

Many thanks for your reply, good to hear that the reasoning is sound. If I add an Express.js middleware I would still need something to distinguish requests from Cloud Functions right? Because mutations are still routed via HTTP?

I guess directAccess might solve that, but there seem be a memory issue tied to it in the current release. On that note, do you know when the next release will happen? There seem to be many great features that have been merged but not released yet.

Yes. You’d have to use the direct access flag. Or, if perhaps you are using a reverse proxy on top of parse server, you can block the requests to the functions using it. I am not sure about the next release date but I agree if you that we already have a lot of great improvements to publish. I will discuss with the team a target date for that.

Ah, that could work I guess. We’re using Heroku however, so we’re not really in control of the reverse proxy. We could try to check the origin IP at the application level, but then we would have to allow all IPs from AWS eu-west-1 region. The best solution is probably to wait for the direct access flag.

I’m really looking forward towards the next release. Thank you for your hard work! :clap:

1 Like