I have developed an app on Android that uses the Firebase realtime database. aka multiple nodes in the DB store various data collected by my app. For Auth, email/password-based Sign-in and Sign-up are working properly. When I sign-up a new user the auth works but that new user then needs to be granted access to the firebase database nodes the app uses. My app needs to grant this new user access to the firebase database nodes required for app interaction.
In other words, how do I programmatically, via my app, change the firebase node-access/security rules in my app (when I currently only know how to change these via the Firebase browser UI)? I do not see methods in FirebaseAuth to do this. So, where do I go from here?
Also, obviously a new user of my app will not have my credentials but they must be able to add access for themselves to my existing firebase realtime database nodes. How do I this?
Here are the rules I have in place today (where my UID is my actual firebase UID):
{
"rules": {
".read": "auth.uid === my UID",
".write": "auth.uid === my UID"
}
}
I now understand I must set rules to allow all authenticated users to read write data in various nodes of my tree. I do not yet understand how to grant access by node and particularly by a specific uid-based node in a tree where there may be many UIDs for each user. As an example, if my tree is root (top), then messages, then a UID for each user, what is the syntax for an authorization rule that will allow the current user/UID read/write the data in only his/her UID under root, messages, his/her user UID?
Related
I am working on one the Android APP & want to integrate it with the Firebase & it's Realtime Database. I have a list of 1000 users(Excel) with details like EmpId, EmpName, Team, Mobile Number, etc.
I want to restrict my APP only to the users from this list & also want to authenticate them using the mobile number present in the list against there name.
Can I use Firebase Auth for the above requirement & if yes, how to do that?
If with FireBase Auth, this is not possible what is the alternative solution?
Please help.
Firebase Authentication only allows the users to identify themselves. What you're describing is limiting what users are allowed to use your app, which is known as authorization, and Firebase Authentication doesn't handle that.
Luckily you tagged with firebase-realtime-database too, and authorization is definitely built into that. What I'd usually do is create a top-level node in the database that contains the UID of users that are allowed to use the app:
"allowedUsers": {
"uidOfUser1": true,
"uidOfUser2": true
...
}
Then in other security rules you'll check if the user's UID is in this list before allowing them access to data, with something like:
{
"rules": {
"employees": {
".read": "root.child('allowedUsers').child(auth.uid).exists()",
"$uid": {
".read": "auth.uid === $uid && root.child('allowedUsers').child(auth.uid).exists()"
}
}
}
}
With these rules:
Allowed users that are signed in can read all employee data.
But they can only modify their own employee data.
Of course you'll want to modify these rules to fit your own requirements, but hopefully this allows you to get started.
A few things to keep in mind:
The UID is only created once the users sign up in Firebase Authentication. This means you may have to map from the email addresses you have to the corresponding UIDs. You can either do this by precreating all users, do it in batches, or use a Cloud Function that triggers on user creation to add the known users to the allowedUsers list.
Alternative you can store the list of email addresses in the database. Just keep in mind that somebody could sign in with somebody else's email address, unless you require email address verification. Oh, and you can't store the email address as a key in the database as-is, since . characters are not allowed, so you'll have to do some form of encoding on that.
Also see:
How do I lock down Firebase Database to any user from a specific (email) domain? (also shows how to check for email verification)
Restrict Firebase users by email (shows using encoded email addresses)
firebase realtime db security rule to allow specific users
How to disable Signup in Firebase 3.x
Firebase - Prevent user authentication
I know it's late but for anyone who may be referencing this question, my recommendation is blocking functions. You essentially create a Firebase Cloud Function that can accept or deny requests to make an account. Here's what it could look like:
const functions = require('firebase-functions');
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
var allowedUsers = ['johndoe#stackoverflow.com'];
// if they are not in the list, they cannot make an account
// throwing this error will prevent account creation
if(allowUsers.indexOf(user.email) == -1) throw new functions.auth.HttpsError('permission-denied');
});
This way is better in my opinion because the security rules doesn't have to reference the database. Instead, the security rules can allow requests from any authenticated user, because the only authenticated users are ones allowed by this function.
I have made an android app and using Firebase realtime database as backend. In the app i have some In-App purchase products too. These products are abount buying points(such as 150 points, 1000 points etc.). The problem is right now i am seeing that some users increasing huge amount of points to their profile. For the sake of relatime view of firebase database i am seeing that their points increasing like 50k, 100k. But i don't have any In-App purchase product with this huge amount. I am tired of disabling their account & can't find a way to prevent it.
I know some app that are used to hack points/coins like Freedom APK and some other. But these apps require the device to be rooted. So on App launch i checked whether the device is rooted or not. Right now rooted device are not allowed to use my app. Still they are hacking points.
I am using following database rules
{
"rules": {
"Users": {
"$userID": {
".write": "auth != null",
".read": "auth != null"
}
}
}
}
And database structure is:
Users-
uId:
userEmail
userName
userPoints
The workflow of valid point increase is:
User buy a In-App product --> User points increase as per the product value
User watch a rewarded video ad --> User points increase by +8
I want to prevent these hackers to generating points.
I am no expert with android and realtime database but the problem is that the user have write access to the database.
I do not know how but they somehow can manipulate the data which is sent to your database.
You need to validate the data before it is written to your database.
You could do some validation with security rules but in my opinion the easiest way is to use callable cloud functions to validate your data and revoke the write access to your database.
If the user buys points they should call a cloud function which verifies if the data is valid. If the data is valid the cloud function updates the database. This way the user can not manipulate their points.
For my online shop i use cloud functions to verify the cart content on checkout and the users can not directly write to the database.
You should do something similar.
Edit:
Here you could find an introduction to cloud functions.
https://firebase.google.com/docs/functions
And here you could find some information about callable cloud function which i recommend. With a callable function you can invoke the backend function directly from your code without an API call.
https://firebase.google.com/docs/functions/callable
i am building a chat android app that allows users to chat where users can create account and use all the features. It's about to be completed but there's a problem, actually a question.
Is firebase on android safe ?
In my firebase database, i have created a rule as follow:
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
Now, this rule will reject any non authenticated users from accessing the data and pushing data or deleting any of it. But, when user creates an account on my chat app, he/she will be authenticated and my app will allow to make modifications. What if they reversed engineered the app and changed some of the codes and pushed invalid datas or removed some of the values from database coz they are already authenticated ?? How can i prevent that ?
When user creates account in my app i use:
auth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(RegisterActivity.this, new OnCompleteListener<AuthResult>() {
This will create a new chat user for the app. So, user is creating his/her own account and they know the credentials and everything. I am so confused, how can i prevent them from editing my codes ?
You can't prevent malicious clients from executing whatever code they want against your Firebase project. Someone will always find a way to compromise your app at runtime on a device that you can't fully control.
The way to protect your data is through sophisticated security rules that:
Requires users to be authenticated (as you already have)
Decide which users can read and write to which locations in your database
Reject invalid data from being written
This requires a fair amount of thought and effort. You can start with the documentation to learn more.
Please also read this question on Quora for some more ideas.
Sorry if this seems like a dumb question but the Firebase docs go round in circles.
I'm building an Android app and I'm authenticating users using mAuth.createUserWithEmailAndPassword documented here - https://firebase.google.com/docs/auth/android/start/
That's straightforward and I can set the username, email etc. and its all stored somewhere (I've no idea where as its not displayed in the Firebase console) BUT I'm confused about user based authentication - https://firebase.google.com/docs/database/security/user-security in the examples here (and elsewhere on the net) we see the rules starting with users
{
"rules": {
"users": {
"$user_id": {
// grants write access to the owner of this user account
// whose uid must exactly match the key ($user_id)
".write": "$user_id === auth.uid"
}
}
}
}
As far as I can see in the Firebase console there is no users child node in the database generated automatically from mAuth.createUserWithEmailAndPassword. So my question is should I create this or was a users child automatically created I just can't see it?
Its not a lot of work to implement an additional user child node and store user information there but it seems like a lot of duplication given that the authentication procedure has already stored the user information somewhere. The opposite way to ask this question is can I add the db write rules above and expect them to work if I have authenticated users but never added a users node in the db myself?
Why the docs don't spell this out is beyond me
Lets say I have 2 platforms, android and web, linked to my database.
The android is for the users to access while the web is for the admins to access. Both web and android shows different information.
How can I prevent the users from logging in to the web and the admins from the app?
Extra info -the users information are store in /users/uid(firebase generated).
While the admins information are not stored in the database.
You can not restrict login like that.
Web
On successful login, check whether the user is ADMIN or not. If ADMIN allow access to content, otherwise redirect to a error page which shows "RESTRICTED ACCESS"
Android
You can do the vice versa. On successful login, if ADMIN restrict the access.
To protect data at the database level, you have to do in firebase database rules.
Your DB Structure should be as follows:
|
--admins: ['Add admin emails here as an array'],
|
--adminContent: Put admin content here,
|
--userContent: Put user content here
Your database rules should be:
"adminContent": {
".read": "root.child('admins').val().contains(auth.email)",
".write": "root.child('admins').val().contains(auth.email)"
}
"userContent": {
".read": "!root.child('admins').val().contains(auth.email)",
".write": "!root.child('admins').val().contains(auth.email)"
}