What prevents another app to connect to my backend, if they have my MongoDB Realm App ID?

I noticed when porting my app to another platform that the only thing I needed in the app to connect to my backend is the realm app ID. With only this ID, I could:

  • Call Realm Functions
  • Create new app users
  • Synchronize data of those users, and public data
    …and do everything else my initial app can do.

So if malicious developers get this ID, what prevents them from creating another app, and conduct DoS attacks like:

  • Create script to create lots of users
  • Synchronize a lot of data to use bandwidths
  • Send a high number of calls to functions

I would think that to connect to the backend, the app (iOS, Android, etc…) would need some kind of private key to make sure that it’s authorized to send requests, but that’s not the case.

So, is there any mechanism in place to prevent that, and if not, how do you address this security issue?

3 Likes

IP Access list, i guess.

From what I understand, IP Access list allows to enter a whitelist of IP address to connect to the backend. However, when distributing an app on some AppStore, each client will have a different IP and I don’t know it in advance. And even if I did, that doesn’t prevent a malicious user from making another app to connect to the backend with an accepted IP.

Having no real answer to this question worries me a bit. MongoDB dev team, anything to say?

G’Day, @Jean-Baptiste_Beau,

Thanks for raising your query.

For the execution of any of these tasks on your application, you need to be authenticated and you need appropriate permissions to perform actions (the permissions you assign when you create the project).

This also depends on how your Authentication Providers are configured: If Anonymous authentication is left on, then anyone can access your data unless you have sync permissions specified to control the access.

For any changes to the app itself, requires database permissions to the user, and the ID on its own is not enough.

Please refer to MongoDB Applications with Sync section on Application Security Documentation.

I hope the provided information helps. Please feel free to ask if you have any more questions.

Cheers. :performing_arts:

Hi @henna.s,

Thank you for your message. This still doesn’t answer the question though.

Example 1. Creating new anonymous app users doesn’t require any permission. Therefore, one could easily create a script to create 1000 new users per second, which would quickly saturate the database. Is there any mechanism in place to prevent that?

Example 2. Let’s say a malicious user creates an account in the app. This user could then create a script to add 100’000 objects per second to the database, which would also quickly break it. He could also make 1000 function calls per second. Is there any mechanism in place to prevent that?

Thanks for clarifying that.

Hey, hopefully, I can shed a little light on this.

If you are using anonymous authentication then you are correct that it would enable anyone to use your app-id to send requests to Realm, but that is kind of the point. If you want your application to allow users to make requests and navigate around on your page without setting up an account then by definition you are saying that any client should be able to send requests to Realm. This is also the reason that enabling anonymous authentication will give you a warning in the UI and think we document this.

If you want more stringent limitations on who can access your service, then you should be using more strict authentication providers such as:

  1. API Key Authentication: the client needs to know a specific API key in order to connect
  2. User-Password: user authenticates with a username and password
  3. Custom JWT
  4. Lots of others that you can find in the documentation

As for your examples above, hopefully, the description here explains that there are reasons to avoid anonymous auth when you want to guard against attacks like the above, but we also have app-level limits in place to prevent too many requests from saturating an application in any given hour. These are internal and we get alerts when applications get close to the limit and we can raise them (and we do that for many production applications).

We have discussed the idea of adding user-specific limits to realm requests, so I would be curious to hear if that is something you would be interested in and why? Additionally, what specific things would you want to be able to toggle? IE, would total requests per user be enough, or would you want to distinguish by service (graphql, sync, functions, etc)? Would you want to have specific limits for specific users and allow some users to eclipse those limits?

The other security measure is that we have permissions to prevent users’ from performing actions that they should not be able to do, but I don’t think that fully solves your problem which is mostly about preventing request spamming.

Thanks,
Tyler

3 Likes

Hi @Tyler_Kaye,

Thank you for your detailed answer. The security on this subject is indeed what I thought it was.

I think user-specific limits could partly address the concern. However, while anonymous authentication is enabled, a malicious user could simply create other accounts to make more requests. IP-specific limits could be used to prevent that.

In the end, what I was looking for is something similar to what Firebase did with Firebase App Check:
https://firebase.google.com/docs/app-check

It’s a way to authenticate all requests as coming from the right client code. It would be an interesting feature to add to your roadmap.

Cheers

The original poster is raising some valid points but the discussion went by the way of authentication. Assuming anonymous authentication is off and everyone has to log in appropriately. This does not change the fact that with sync on, a user has pretty much access to everything (I know flexible sync is coming, and I do see a lot of benefits there, but for my questions here, I am going to ignore that for now because it will still have holes)…

Lets say I am making an app for timekeeping. I want other companies purchase my services. I can easily segment each company into thier own partition. In that partition, the company will add multiple users so they can punch in and punch out. Every user would have access to every record in that partition. Now, a disgruntled employee who may also know a bit of programing, could theoretically delete every single record in that portion just by simply knowing the app id and having a valid login. (This app would have a web based interface in addition to a mobile app and that app id would have to be exposed to the client unless I did everything server side which kinda defeats the purpose. Even if I didn’t use a web based interface, we are just hoping that the id is never exposed).

How are companies today securing data in a realm sync app. Or is this a case of if you need to secure data, realm sync might not be the best option for you? I know big companies use realm sync, I just can’t get past how open the database is.

One example I can think of is using triggers to help validate and or reject changes (just showing how I am trying to think outside the box. I haven’t gone down the road to see if this is feasible or would cause performance issues if there were triggers on every write operation).

1 Like

Hi, I think the situation you are describing is, in a lot of ways, one of the many reasons we created Flexible Sync which has:

  1. Document-level permissions (as opposed to partition-level)
  2. Expressive permissions (can use any MDB operator on a queryable field)
  3. Role-Based Permissions: different users can have different roles
  4. Operation-Based Permissions (Coming soon): distinguishing between Insert/Update/Delete/Replace within rules
  5. Field-Based Permissions (Coming soon): giving read/write access to specific fields for different roles

Partition-based sync has a fundamental limitation built into it: the partition.

And because of that, you are correct that not all solutions fit into that limitation, which is why we removed it.
For people who are using this in production, one fairly common partition key is “user_id” so that you can isolate the permissions of a partition to only a specific user. So in your hypothetical case above, you would want to partition on a “compound” partition key which is something like { userIdCompanyId=“userd1_companyid1” }. This is a fairly common pattern we see in customers of partition-based sync, having one field be a combination of several other fields and that is what is the “partition”, and in that sense, the permissions are applied more granularly. However, this is obviously just masking the underlying problem in a lot of ways.

Apologies if this does not answer your question. Partition-based sync is great and performant, but built into the entire system are limitations with what you can do with it from a schema modeling and permissions perspective. This makes it great if those limitations align with your application, but we know that people want to remove these restrictions and be able to let their application guide their
schema and permissions model and not the other way around.

1 Like

This is very helpful to know that I am at least understanding the concepts (and that I am not missing anything).

Are there rough timelines as to when everything should be available for production use? If it is months, I can probably program knowing its coming, if we are looking a year or more, I would need to plan on something different.

I am also very curious as to how opetion and field based permissions can be applied in an offline first world. Should a commit fail because of security permission, what would the ramifications of that be.

Hi Robert,

We hope to go into GA this summer, so hopefully, that aligns with your timeline.

Before then, we hope to address the following:

  1. (In Progress) Performance optimizations in the propagation of changes through the system
  2. (In Progress) Allowing lists as queryable fields
  3. (In Progress) Compensating Writes
  4. (Upcoming) Introducing the FieldBases/OperationBased permissions

None of these should lead to any breaking changes ideally and we do not expect to break the API before the GA date. It is most fit and finish as well as removing some initial limitations we placed on the system.

Your question about permissions is a very valid one and why we have a project called “compensating writes”. In an offline system, we cannot trust the SDK to synthesize writes that is has pemissions to make. Currently, when this happens this will result in an error being returned to the client, but the goal of Compensating Writes will be to (a) alert the SDK when this takes place and (b) unwind those changes safely while continuing to sync.

Please let me know if you have any more questions. Your questions are very good, and I think in large point to why we wanted to build Flexible Sync.

Thanks,
Tyler

1 Like