I'm trying to implement role-based security for Cloud Firestore. Am I understanding correctly that users retrieving stories in Google's example at https://firebase.google.com/docs/firestore/solutions/role-based-access would see the roles other users have?
How would one design against that?
I assume by using another collection & using Get?
Tad vague, but...
I am implementing role-based access in an app, but not following the example, for the very reason you mention: if a user can read a document, then they read all of the document.
My approach is a bit less direct.
The roles are stored in more secure records where only someone authorized to create the roles has access.
A Cloud Function is used for a user to fetch role information - that
way the user does not have direct access, but the secure back-end can
validate and "filter" the data appropriately (in this case, whether they are "managers" of a business property)
Another Cloud Function adds role information onto the Users account
Token as customClaims (has to be done in secure environment, not client)
Security rules validate access against the customClaims - which all
happens in a secure environment (no need to trust the browser)
More convoluted, but it does control role visibility.
Related
I am trying to determine if the following scenario is possible with flutter and firebase:
we have users within the company who will be given access to the app, where on the homepage will be a signup another user button where they enter in that user's email and password, they get signed up, and then the original user specifies custom fields for the 2nd user, such as company name, role, position, etc.
Is this possible with flutter and firebase?
Have asked the flutter google group and was told about custom authentications, but from what I see that is just an external authentication system and doesn't show me how to let one user create another users profile with fields.
Any ideas?
The first thing to consider is whether those properties need to be in the user profile at all. The user profile is sent with every request, and should only contain information that is relevant for securing access. If you have additional information to store about the user, you should store it elsewhere (such as in one of Firebase's databases) using the UID of each user as its key.
Assuming that the information is about security (such as the role seems to be, there is no secure way to let one user set security properties (typically referred to as claims) from client-side code. As soon as this is allowed from client-side code, anyone could set such properties for anyone else. That's why setting custom claims for a user is only possible with Firebase's Admin SDKs, which are designed to run in a trusted environment - such as your development machine, a server you control, or Cloud Functions.
There are a few other options, but it's important to realize they're all implemented on top of the above approach.
There is an experimental extension that allows you to set auth claims by writing a document into Firestore, which something like this (JavaScript syntax, but the Flutter code will be similar):
db.collection("user_claims")
.doc("abc123")
.set({
role: "admin",
groups: ["example1", "example2"],
});
Now of course you'll want to make sure that you secure writing to the user_claims collection, as otherwise you'll end up with the same security risk I mentioned in the first paragraph, where everyone can claim any role they want.
Alternatively you can write your own server-side API (for example on Cloud Functions) that you expose to your application, and that then calls the Admin SDK. Here too, it is important to secure access to this API, to ensure only authorized users can call it.
So I would like to implement a view counter, but I'm not sure if there's a way to do it client-side only. AFAIK there is no way to use the client's IP address without a server to verify it and firebase doesn't have a support for this, how could I implement a view counter for unauthenticated users?
Obviously authenticated users are no problem since I can use the uid for them, but is there a way to distinguish unauthenticated users?
You'd use Firebase anonymous authentication for that. Using anonymous authentication identifies the users with them having to sign in.
Your application code essentially defines an identified session this way, which you can use on the back-end (or if you're using the Firebase database in your database's security rules) to restrict the number of votes each such session can cast.
If a user logs into my Firebase store with Google authentication, the client gets access to all sorts of useful user-specific information, like the user's name and email. I might want to put this information in the store, and the client can certainly send it along in a write request. But as far as I know, there's no way to validate (on the server side) that this information is correct. There is nothing stopping someone from using a second client to send fictitious metadata.
(For instance, take a look at the skeletal auth variable which is accessible from security rules. It doesn't contain the information I need for validation.)
How do people deal with this kind of situation?
Only limited information about the user is available in the auth variable in security rules.
To access more information, you'll have to store that information in the database when the user is created or signs in. Most developers add a /users node to their database for this reason.
You can then look the extra information up in your security rules with something like root.child('users').child(auth.uid)...
The process is covered in the Firebase documentation section on Storing User Data.
Maybe I wasn't searching the documentation properly, but what is the recommended standard way of treating authorisation levels/classification for admin users in firebase?
Let's say in classic admin user scenario, where admin should have the access to all user accounts while normal authenticated users have write access to only specific objects.
I came accross this post but the solution using firebase secret is not good enough in this case. Firebase secret is meant to be used by server and setting up the extra server authenticating admin users and talking to firebase is certainly the option, but the complexity and programming overhead is increased.
The better option is using the security rules. Question here is - Does not this generate an extra overhead for each single read/write operation? The number of general users could be in millions while there is only handful of admins. Secondly you do not want non admin to be authenticated by management tool even though they will not be authorised to do anything.
Third option - however I don't know how would I achieve this - limit authentication to admin interface webapp only to specific admin users or set the limit for the specific domain. Let's say only {name}#myappadmin.com will be allowed to be authenticated thus I will not need to do the authorisation check before each operation. Is this even possible using only Firebase as backend?
An example is say i have a child with lots of data in it and a user wants to attack my firebase to slow it down and increase my upload limit and sets to read this child over and over again not from my app but from their own creation.
How would i prevent this from happening when the child is a public child in that it does not require a user to be logged in to be read?
Is there a way to only allow a certain domain to access a firebase so that other users cannot just access my data from their domains?
Since all the data can be read via javascript and the javascript can be changed by the user can this also happen when someone changes the code on my site. Also is this a potential problem with all databases RDBMS or non RDBMs and not just with Firebase?
You might want to check out the "anonymous" login option provided by Firebase Simple Login: https://www.firebase.com/docs/security/simple-login-anonymous.html - this lets every visitor to your site authenticate with Firebase, and you can setup your security rules such that only anonymously authenticated visitors to your site can read data.
Most production apps will employ the security rules to restrict access to their data. Learn more about Firebase security rules here: https://www.firebase.com/docs/security/security-rules.html