MongoDB Realm - Block data leaks - realm

I am in the stage of setting up MongoDB Realm sync with Schemas but I have a question regarding data breaches.
My schemas looks like this:
User {
id
name
groups[] (ids)
}
Group {
id
name
members[] (users - Inverse Relationship)
}
I would like the user to login and receive their user data which includes the groups they are members of. How can I define the sync rules (or another way?) to stop anyone reverse engineering my app code and change the partition (group ID) and get access to other groups?

Related

How to enforce row-level insert and update permissions in Hasura based on an arbitrary user property

Here is a description of my tables
event {
id
organization__id
}
user {
id
}
organization {
id
}
organization_user {
user__id
organization__id
}
How can I restrict a user in order to allow him to insert/update event with only organization__id he belongs (through table organization_user)?
You definitely do not need to add any token session variable values other than an X-Hasura-User-Id which I assume you have already implemented.
Using Hasura correctly is all about making the proper relationships between your different tables.
It is important to remember, Hasura can use both object and array relationships for row level permissions lookups.
I am going to assume that the following relationships exist (if they do not, you can create them easily).
event => organization
organization => orgUsers (organization_user array relation)
organization_user => user
Event then has a direct lookup path to user.id and you can check that it equals the X-Hasura-User-Id. Although this is an _eq check, remember: the orgUsers array lookup in that path makes sure that if any orgUser.user.id matches, they will have row level access.
Comment if you need clarification of any of these points.
It's hard to say without knowing you permissions and authentication scheme, but you can accomplish this by using session variables in your row-permissions settings (docs).
First, you'll need your users to have a value in their session token that maps to the organization__id column in your database. For example, suppose your session tokens have a property called X-Hasura-Organization-Id.
Next, disable insert and update permissions on the organization__id column in the event table.
For insert permissions, configure a column preset which sets the organization__id value based on the user's session token value for X-Hasura-Organization-Id.
And, finally, to prevent users from updating records outside of their organization, you can configure a row-level permission rule which checks that the X-Hasura-Organization-Id in the user's session token matches the organization__id of the row they wish to update.

NoSQL query of items,lists, Groups and Users using Firebase

Am looking at the data structure in this post and want to know how you would go about getting the emails of users who belong to a certain group when they could belong to several groups and the GroupID stored against that user is the current group they are participating in?
Do you store the email addresses with the userid under the "members" or, instead, for each member of the group, get that user's email address from the "users" document userid (this would mean iterating through the group/members collection and doing a query for each user. Not very efficient).
Am used to SQL so this is all new to me.
You should have a single node for each user
/users/UID/emails/
/users/UID/emailunread/
/users/UID/settings/
/users/UID/details/
/users/UID/payments/
So you can simply do a subscription for a singular node path this.myDatasubscription = this.DB.list('users/' + this.uid).snapshotChanges() ensuring changes like new emails or account settings will detected and rolled out in real time back to the app, so your are using angular/ng or something similar client side then your variables {{this.email_list}} should update real time with no page changes.
Take a look at this one.
error: Property 'getChildren' does not exist on type 'DataSnapshot'

Custom Authentication in Google Firebase

I have a question regarding authentication using Google Firebase.
For an app, I want to build an authentication similar to the one Slack uses: first, the user provides the input as to which group they want to log in to. If there exists a group with the same name as provided in the input, the user is then taken to a login/signup screen.
I've thought about storing users in the realtime database as follows, but I think there must be a better way to do this (since I don't think I can use the firebase authentication in this case):
groups: {
"some_group_name": {
"users": [
"user1": {
.. user 1 information
},
"user2": {
.. user 2 information
}
],
"group_details": {
"name": ..,
"someGroupDetail": ..
}
},
"some_other_group_name": {
...
}
}
I haven't realized if there is an obvious answer yet, so I'm open to suggestions. How would you suggest I tackle this?
Thanks
PS: I'm building the application using Nativescript and Angular, and (so far) there is no server or database involved other than Firebase.
Another suggestion that might work, is by using Firebase Auth Custom Claims. That way, you only need to store the group ID and group name in your realtime database, without worrying to keep changing the database each time user is added or removed.
This is one way you can do it:
Store database exactly like you have it, with it's group ID and name.
In your backend script (I recommend Cloud Function), each time a User is registering themselves, add custom claims in your user: Specifying what group is the User belong to.
Every time user authenticate, retrieve the group ID from custom claims. And there you get it!
Note: be careful not to put too much information in your custom claims as it cannot exceed 1000 bytes.
Read more about it here: https://firebase.google.com/docs/auth/admin/custom-claims
I would suggest you to implement Root-level collections.
Which is to create collections at the root level of your database to organize disparate data sets(as shown in the image below).
Advantages: As your lists grow, the size of the parent document doesn't change. You also get full query capabilities on
subcollections.
Possible use case: In the same chat app, for example, you
might create collections of users or messages within chat room
documents
Based on the reference from the firebase cloud firestore
Choose a data structure tutorial (I know you are using Realtime database but structuring the database is the same since both are using the NoSQL Schema)
For your case:
Make 2 Collections: Users, Groups
Users: User info is stored in the form of document
Groups: In the Groups Collection, here comes the tricky part, you can either store all groups subcollection under 1 document or split into multiple documents (based on your preference)
In the group-subcollection, you can now store your group info as well as the user assigned where you can store user assigned in the form of array, therefore whenever a user access the group, query the user assigned first, if yes, then allow (assuming users can view all group)
You do the thinking now

How to restrict access to files to group members?

I have a chat app where users can send photos in private or group chats. Each private or group chat has a unique chat id: /images/<chat id>/image.jpg
How would one secure the access to this files so that only the chat members can view them? In the Firebase database I have a node with a structure like: /members/<chat id>/member1: true.
Is this actually necessary, since the links are only posted to the corressponding chats?
Can any authed user actually browse through the files saved in the Firebase storage? Or is this prevented by design?
The eternal question. It's discussed a few places (Google Group, Storage Docs, Github Gist), but the TL;DR is: at present, there's no way to read data from one service in the Rules of another. For services, you can do one of two things:
Convey group information in a custom token
Convey group information in custom metadata in the service
One example of this:
// Allow reads if the group ID in your token matches the file metadata's `owner` property
// Allow writes if the group ID is in the user's custom token
match /files/{groupId}/{fileName} {
allow read: if resource.metadata.owner == request.auth.token.groupId;
allow write: if request.auth.token.groupId == groupId;
}

How to use Session in SignalR connect

In my database a user has some area permissions.
What I want to do is to add this areas into Groups of SignalR.
So, when user sign in, I get this groups from database and save in Session["groups"] and when user connect to signalR, I use this session to add in Groups.
Something like this:
public Task Connect()
{
var groups = (string[])Session["groups"];
foreach (var group in groups)
{
Groups.Add(Context.ConnectionId, group);
}
}
How can I do this or something like?
As mentioned here SignalR Hubs - Managing groups
You can add connections to groups and send messages to particular groups. Groups are not persisted on the server so applications are responsible for keeping track of what connections are in what groups so things like group count can be achieved.
That means that you have to provide your own structure such as a Dictionary to hold your data.
For example, a Dictionary to hold group name as the key and List of areas as values (or the other way around if it suits you best).
So for each new area of your user, first update this Dictionary and then subscribe the user to the groups that were changed.
Groups.Add(Context.ConnectionId, group);
Nevertheless take a look at the link above and also here Topic based pub sub design patern. Do not hesitate because of the WCF on the title. Get a closer look on the way he implements the Filter class

Resources