I have a use case of users and group. Data gets saved into dyanmodb. I am struggling with securing the data.
I have user and group in Cognito. Data is saved/retrieved via DynamoDB, but I want to encrypt the data so that even I don't see it or even I can't modify it but all the users within the group can view it. The hash and range key are fine, no need to encrypt but can work if encrypted.
Imagine there are users like user1, 2, 3 ,4 and group 1.
User 1,2,3 are in group 1. Now only User 1 can modify his data but User 2 and 3 can view it. User3 and 4 can't view or write. I can have this as an application logic. But I want to encrypt the data so even as the Admin of AWS account I can't modify it. Ofcourse I will be able to delete it but thats fine, user will anyway know this
Is that possible?
Related
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'
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
I'm trying to implement a short token system to allow players to share a 4 digit generated token so other players can locate and join their private game.
I am having trouble figuring out how to model this in firebase as I am new to flat data structures.
Here’s a simplified version of what I currently have implemented.
Users
{4321}
displayName
….
openGames
{1234}
games
{1234}
title
…
openGames
{1234}
gameState
token
public
...
timeStamp
tokens
{AcFk}: {1234}
Assumptions
I do not want logged in users to be able to iterate the tokens, openGames or games nodes.
Using a Token
When a player uses a token to find a game, I pull the token from the token table root.child(“tokens”).child({AcFk}) and use the value to find the open game.
Security
Only allow a user to write a token for a game that they own. This is done by checking that a game with the key exists under their user profile when creating the key; enforced with a security rule; “.write”: “root.child('games').child(auth.uid).child(newData.val()).exists()”
Only allow a user to write one token per game.
Problem
I don’t understand how to enforce the final one token per game rule. A malicious user could flood the table with fake tokens for a game they own and exhaust the token keyspace or increase likelihood of a collision requiring a new key generation.
tokens
1111:{1234}
1112:{1234}
..
ZZZZ:{1234}
I guess I am trying to enforce a unique value rather than key. If I try and reverse the keys to acheive this I end up needing to iterate the tokens node (bad, now all tokens are public) to find the corresponding gameKey - mref.child(‘tokens’).orderbyvalue().equalto({token})
As there is no way to iterate in a security rule, I ended up trying a second index with the keys reversed to place some sort of lock and just got lost.
I think this is a weird one:one relationship that is complicated by the fact I don’t want people to iterate my data.
Any help would be appreciated
If I'm understanding this correctly you want a user to be able to join a game only once. If so you could reverse the key and value in your tokens object for example
tokens
1234:{1111}
1234:{1112}
..
1234:{ZZZZ}
Then when a user join for a second time(or multiple times) their first token will be overwritten so the above example becomes
tokens
1234:{ZZZZ}
I'm building a simple web form which allows user to edit there data like email, emergency contact etc.
The edit form is rendered using Asp.NET MVC 5. Proper html fields are rendered for Id, email, emergency contact etc.
Lets say the request to save the data is received by the following controller method.
SaveData(recordId, email, emergencyContact)
{
;
}
Question: How do I make sure that recordId was indeed the id that was rendered as part of the edit form? We don't want this user to update another user's record.
I have the following options in mind
1. Create a hash of the record id and send the hash as well.
2. Ensure user is authorized to modify the record indicated in given record id.
Is there any other way? Does MVC 5 provide any features so that I don't have to put this sort of logic in my application logic?
Typical approaches are:
Store the ID of the record as a hidden field. If you are concerned with hijacking, encrypt the value and decrypt on the server.
Store the ID of the record in session; this way, you always pull back the record and keep the value on the server. But when session dies, so does the link to the record.
Yes I'd highly recommend check permissions to the record if you store the ID in the URL.
I am developing an early version of my site and before I create the production version, I'd like people's opinions on whether I'm going about things the right way. The main objective is to allow users to share playlists. I have the User table (ASP.NET Membership), Playlist table and a permission table. I'd like a user to create a playlist and grant/deny access to it for a given user. My approach to this is to have the permission table contain a "pStatus" column where 0/null = deny, 1 = read.
When a user requests permission to access a playlist, the creator chooses the pStatus enumeration. The column is then changed accordingly for the recipient. When accessing the recipient's profile page, a scan of the column is done to check all playlists the recipient has access to and the relevant playlists are displayed.
Is this an efficient and secure way of doing things? Or is relying on one column not enough?
(nb - playlists can be considered to be similar to Facebook groups)
Thanks for any advice
I would use some sort of bitmask in the n-m relation table I'm guessing is in between User and PlayList (i.e. a table named UserPlaylist, because 1 user can have access to more than 1 playlist and vice versa 1 playlist can be accessed by more than 1 user).
If you define the needed permission levels up front (i.e. 0 = no access, 1 = read, 2 = write, etc.), you can just add a column to the UserPlayList table, that represents the access level.
So the UserPlaylist table will have 2 foreign key columns of which the combination should be unique (i.e. define the primary key to be the 2 foreign key columns) and a column that holds the level of access in the form of a bit / integer.
So Permission has foreign keys to User and Playlist. Is there any reason for the third column specifying permission level? It sounds like it should be: If a row exists in Permission, the user is allowed to access the playlist.
Otherwise, that sounds good to me.