Firebase real-time database authentication for multiple users - firebase

I was looking for simple authentication mechanism for multiple users in Firebase real-time database. For ex: I don't want all millions of users to login using email and password to access Firebase real-time.
I came across creating custom token from the below documentation.
https://firebase.google.com/docs/auth/admin/create-custom-tokens
I want to understand clearly about that. Is this something that helps to authenticate multiple users (grouped as one) programmatically via custom token instead of each user has to authenticate using email address and password? or This is different from what I thought?
Please advise.

No, custom tokens are used when you have your own database of users that have already signed into your existing service with some other form of credentials that you provide.
If you don't have your own database of users, custom tokens won't help.
Also, there is no such thing as "grouping" users for the purpose of authentication using Firebase Authentication. Each user has their own distinct identity with their own credentials that are dealt with independently of each other.

Custom tokens are used when you have your own authentication service but want to allow your users to access Firebase services. If you want your users to be able to use the database without an email and password, you can use a provider such as Google or use Anonymous authentication, which is when the user is logged in and can access the database, but don't have to prove that they're themselves. You can always add them as an actual user later.
To allow authenticated users to access the database, you can use these rules:
// These rules require authentication
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
Database Rules Docs

There is a difference between when a user signs in (authentication) and when they gain access to your database (authorization).
There is no way to prevent users from authenticating with Firebase Authentication's built-in providers that you've enabled in the Firebase console. But it's quite easy to only allow specific users access to the data in your database with Firebase's server-side security rules.
For example, if you only want specific users access, you can set up a whitelist of their UIDs:
allowedUsers
uid1: true,
uid2: true,
uid3: true
Now you can write a simple security rule that only allows users in this list to read your database:
{
"rules": {
".read": "root.child('allowedUsers').child(auth.uid).exists()"
}
}

Related

Firebase rule to only allow users to write with their device token

Assuming users don't create an account and only use device token, one can have this structure:
users/${device_token}/posts
Now, how can you protect that each user can only access their own posts?
I have used this in the past: .write: "$uid === auth.uid" when I had each user create an account and log in. How can I get a similar result when users don't create an account and just use device token?
Only the currently authenticated Firebase Authentication user is available in Firebase Database security rules. Since the FCM token is not part of a user object, the FCM device token is not available in the Firebase Database security rules.
So you will need to use Firebase Authentication to ensure that there is a current user. Luckily you can use anonymous authentication to ensure there is a current user without the user having to explicitly sign in. This makes the auth.uid in your security rules work again.
The next step is to associate the user profile with the FCM device token. I can quickly think of two ways to do that:
Store the token in the user's profile as an additional claim.
Store the token in the database associated with the UID.
To store the token in the user's profile, you'll need to use the Firebase Admin SDK. This means this that you need to run this code on a trusted environment, such as a server you control or Cloud Functions. Once you have this, setting a custom claim is as easy as:
admin.auth().setCustomUserClaims(uid, {deviceToken: "....."});
And you'd use it in your security rules as:
".write": "auth.token.deviceToken === '...'",
Read the documentation for more info as there are some limits to what you can set.
A more flexible, but more cumbersome, approach is to store the token in the database. To do this you add a new top-level node to the database, where you store the token for each user:
tokens
$uid: "..."
You'll want to secure this part of the database so that users can only write their own token.
After that you can access this node in the other rule to check their token. For example:
".write": "root.child('tokens').child(auth.uid).val() === $token".

Database rule in Firebase: Can we setting each rule for each application in the same project? [duplicate]

My problem is my project has 2 application. One application just run in a specific mobile device which we known, it interact with firebase without authenication. The another is run in many mobile devices, it must sign-in into firebase to communicate each other.
So, what I want to do is how to configure database rule in firebase to 2 app can use the same the database? Thank everyone very much! Appologize for my bad english.
You cannot secure database access to allow a specific app or a specific device. See How to prevent other access to my firebase.
But a device can easily be mapped to belong to a specific user, if you use Firebase Authentication. You could even use anonymous authentication if you don't want to require that the user signs in. With Firebase Authentication each user has a unique user id (UID in Firebase terms). And when you know the UID for the user, you can secure access to the database based on that UID.
An example from a recent project:
{
"rules": {
".read": true,
".write": "auth != null &&
root.child('config/whitelist').child(auth.uid).exists()"
}
}
So here, we allow writing if the signed-in user's UID is present under a node /config/whitelist. E.g.
config
whitelist
"jn0BrHQqUEYSjqvqfqzbJTMOlZ82": true
"ytEtWqOfLkRk3OUjTKBtZnTehZc2" true

Writing Firebase database rules when user information are on another server

I need to implement chatting for a mobile app that talks to my own server, so the registered user information is on my own server. So, if I use firebase real-time database for chatting, how do I write the security rules like these:
".read": "auth != null", ".write": "auth != null"
So the scenario is, my user's information are on my own server, in my own database. I want to use firebase to implement a chat
How do I write the database rules that prevents anyone from reading the messages from database (by hitting the URL maybe ?)
Yours is precisely the scenario that Firebase Custom Authentication was made for.
On your server you authenticate your user against your own user database, then you mint a JSON Web Token with the information about that user that you want Firebase to know. At the very least the token should contain a uid, but it may contain more information that you can then access in your security rules. Once you've created the JWT, return it to your user.
In your app, you then use the JWT to sign in with Firebase. For example on Android that means, you'll call the FirebaseAuth.signInWithCustomToken() method.
For more information see the Firebase Database Server documentation.

Firebase createUser with Email/password authentication [duplicate]

I am using the Simple Login Email / Password Authentication functionality of Firebase.
I would like to manage users through Forge only. I don't want users to be created via the client app.
However I would still like to let them login/logout though.
Is this possible?
You can't prevent users from being created on the client using simple login. There are two options you can utilize instead:
Simple Login "accounts" are really just tokens
Simple Login is just a convenience wrapper that creates Firebase tokens. There is no limit on how many accounts can be stored and they have no affect on your Firebase usage. With this in mind, there's really no reason you need to restrict creation of accounts.
Instead, just utilize security rules to control access to data. When an admin creates an account, have them also add a profile into the data. If only an admin in Forge is allowed to create the profile, then someone could create an account, but it would be superfluous and pointless, since all it does is give them an inert token.
A security rule to enforce access to data:
".write": "root.child('valid_account/'+auth.uid).exists()"
A security rule that allows users to edit their profile but only Forge (admin: true) to create them:
"profiles": {
"$uid": {
".write": "data.exists() && auth.uid === $uid && newData.exists()"
}
}
Creating your own tokens allows complete control
If you're terribly OCD and don't like that approach, then you can cut out Simple Login. As stated previously, it just creates tokens on your behalf. So simply create your own.
In this way you have complete control over account creation and token generation.

Does Firebase create accounts for all authentication types?

Email registrations are seen as a new record under the Simple Login → Email tab in our forge.
But what happens when a user Signs In using one of the OAuth2 logins like Facebook or Google?
Take the example right off the site and apply multiple contexts to it:
{
"rules": {
".read": true,
"comments": {
"$comment": {
".write": "auth != null",
".validate": "auth.id == newData.child('userid').val() && newData.hasChildren(['userid', 'body']) && newData.child('body').isString()"
}
}
}
}
If a user logs in with a Facebook account will Firebase create a new auth record and scope security rules in the same context as an Email/Password login?
If so are those registrations viewable in the same way as our Email auth type? Do you perform operations on those records like (delete) in the same way?
What would be the best way to scheme a master userId collection that enables a user to tie multiple account types together? (Facebook, Google, and Email all tied together)
Keep in mind that "creating a user" in that console (and in Firebase Simple Loign email / password auth. in general) only generates a new mapping between an email address and a password, and gives that account a unique, auto-incrementing id.
Firebase Simple Login will not automatically store any data in your Firebase, though upon login, it will automatically generate a new Firebase auth. token against which you may write security rules making use of the auth variable.
Login methods using any other provider currently store no data, though in the future there may be more functionality there. Logging in with Facebook / Google / etc. will also fetch a bunch of useful user metadata and send it down to the client, in addition to creating a Firebase auth. token for use in security rules. To see the contents of the auth variable across all providers, see the 'After Authenticating' section on each of the Simple Login Providers docs pages, for example: Facebook. There is no notion of a delete for any provider except for the email / password provider.
If you'd like to have user accounts that are linked to multiple social credentials, it can be done, though it is a little clunky (and manual) at present. See How can I login with multiple social services with Firebase? for a thorough walkthrough.

Resources