Loop user registration for firebase - firebase

Could someone please suggest how to properly set up a loop for registration? The idea is that I have an excel file with 500+ users ( emails and raw passwords ) which I wanted to register. As I understood the best thing is to read the excel file in js , assign for each email and password a variable and call the createusernamendpassword method in firebase upon each iteration ? Please don’t suggest using the auth:import as it suggest you to have already salted and hashed passwords ( as I don’t have them ). The whole point is to create in bulk absolutely new usernames

Using the Adkin SDK from your local machine or a trusted environment like a server or cloud functions, You can run the Create User from the auth package inside a loop. it is important to implement tracking if you are doing it in Firebase Cloud Functions as the 9-minute timeout (if configured) might not be enough to finalize processing.
async function ProcessUsers(){
for(const user in userList){
await admin
.auth()
.createUser({
email: 'user#example.com',
emailVerified: false,
password: 'secretPassword'
})
.then((userRecord) => {
// See the UserRecord reference doc for the contents of userRecord.
console.log('Successfully created new user:', userRecord.uid);
})
}
}
you can do several improvements from the base script such as setting up a queue to ensure the values are processed before batching more together. But this is sufficient to get started.
Source: https://firebase.google.com/docs/auth/admin/manage-users#create_a_user

If you do this with the regular client-side SDKs, you will quickly be rate-limited as quickly creating accounts from a single client is a common abuse scenario.
The Firebase Admin SDKs are designed to (only) run in trusted environments, such as your development machine, a server you control, or Cloud Functions. And these Admin SDKs have dedicated APIs to bulk import users. That is the best way to go about this.
You can also use the Firebase CLI to but import the users, which is quite similar.
Neither of these options takes a so-called cleartext password though, so you'll want to hash those first as shown on bojeil's answer here: can i import csv with real password to firebase authentication

Related

Firebase auth - how to un-protect listCollectionIds method in REST API

It seems that I can use the get method without any authorisation, but listCollectionIds needs some key to access, as I'm getting the 403 error without it.
I am able to access that data when I'm using the OAuth 2.0 on Google's API Explorer utility.
Firestore security rules are currently set to allow everything. Is there a way to disable authentication for listCollectionIds?
You cannot list collections using client SDKs or remove any restrictions on it. Only the Admin SDKs can access the listCollections() method using service accounts. The documentation says,
Retrieving a list of collections is not possible with the mobile/web client libraries. You should only look up collection names as part of administrative tasks in trusted server environments. If you find that you need this capability in the mobile/web client libraries, consider restructuring your data so that subcollection names are predictable.
That being said, the best you can do is store list of collections (or sub-collections) in a document somewhere else in the database.
Other way around this would be creating a cloud function that'll fetch list of collections on behalf of your users.
exports.getCollections = functions.https.onCall(async (data, context) => {
// Authorize user if needs
const collections = await admin.firestore().listCollections()
return collections
});

Fake users in firebase with #gmail.com accounts

I have a firebase project.
The next sign-in methods auth are enabled:
Google
Facebook
Apple
Anonymous
A mobile app interacts with the firebase.
Each day I get some weird new users sign-ups with fake accounts with the pattern: [name][numbers]#gmail.com. They don't do anything except sign up via google oauth once.
Is it possible to prevent it? Maybe I missed something with the google oauth configuration?
Updated:
Also, I noticed that these sign-ups started to occur when I had sent out the mobile app to google/apple verification. May these two events are correlated?
New accounts created coz of Play market Pre Launch Report
You can change Pre Launch Report settings to change it's behaviour (e.g. specify test account to use in auth)
If you are sure those fake users have a specific pattern from their email address, I would make a trigger function on Cloud Functions for Firebase.
You can use functions.auth.user().onCreate() event handler like below.
exports.checkFakeUser = functions.auth.user().onCreate((user) => {
// You can check if the user has suspicious email patterns and delete them here.
});
Or you can also make a Schedule function on Cloud Functions for Firebase and daily check if there are fake users and automatically delete them.
Plus, it would be a good step if you figure out that fake users still joining even you didn't expose your mobile app anywhere if you want to find out the reason how they are joining.
Add the following Cloud Function will help you on check the email and delete the fake user
exports.checkFakeUser = functions.auth.user().onCreate((user) => {
const list = user.email.split(".")[1].split("#")
const isFake = list[0].length === 5 && list[1] === 'gmail'
if(isFake){
admin.auth().deleteUser(user.uid)
.catch(function(error) {
console.log('Error deleting user:', error);
});
}
});
You can't stop specific accounts from being created, as the underlying Google Auth APIs are accessible to anyone with an account. You could manually delete them, or write a program to delete them (bearing in mind that you could also be deleting actual user accounts).
Or if you suspect abusive behavior, you can contact Firebase support to report that.
Check, these e-mail addresses will be re-logged when they upload a new version to google play. The most likely reason for this is that google keeps your application to a number of tests with its automation infrastructure.

firebase.auth().deleteUser - Error: "deleteUser is not a function"

I have few authenticate users in the user list. And I want to remove one of them. Firebase documentation suggest me to use this code for remove any user.
admin.auth().deleteUser(id)
.then(function() {
console.log('Successfully deleted user');
})
.catch(function(error) {
console.log('Error deleting user:', error);
});
So I use it in my project like this way. I use firebase.auth instead of admin.auth. so my code is like this.
firebase.auth().deleteUser(id)
.then(function() {
console.log('Successfully deleted user');
})
.catch(function(error) {
console.log('Error deleting user:', error);
});
But it not working. Shows an error like this
deleteUser is not a function
The deleteUser function is defined for the Firebase Admin SDK. It appears that you are using the client-side JavaScript SDK. The Admin SDK needs to run on your web server, whereas the client-side JavaScript SDK would run in the browser.
For an overview on how to delete an individual user (or multiple users), see Delete a user.
Firebase Admin SDK
The Admin SDK lets you interact with Firebase from privileged environments to perform actions like:
Read and write Realtime Database data with full admin privileges.
Programmatically send Firebase Cloud Messaging messages using a simple, alternative approach to the FCM server protocols.
Generate and verify Firebase auth tokens.
Access Google Cloud Platform resources like Cloud Storage buckets and Firestore databases associated with your Firebase projects.
Create your own simplified admin console to do things like look up user data or change a user's email address for authentication.
If you are interested in using the Node.js SDK as a client for end-user access (for example, in a Node.js desktop or IoT application), as opposed to admin access from a privileged environment (like a server), you should instead follow the instructions for setting up the client JavaScript SDK.

How to avoid hit rate limits when using firebase authentication in the backend server?

I implement user signup logic in my nodejs backend server. It uses firebase for username and password signup. Below is the code used in nodejs:
var firebaseClient = require('firebase');
firebaseClient.initializeApp(config)
firebaseClient.auth(). createUserWithEmailAndPassword(req.body.email, req.body.password).catch(function(error){
console.log(error);
})
the problem for this approach is that firebase has a usage limit which is 100 accounts/IP address/hour. All users who signup in my application will go to my nodejs server first. That means firebase will think there is only one user. It will meet the usage limit very easily. I know I can put the signup process in the frontend but I don't like doing this. Because my signup logic needs to save something in my local database as well. I wand them to be in one place. Does anyone know how to handle the usage limit in my case?
The Firebase-Auth AdminSDK should not be rate limited so you can use it on your NodeJS server without any problems to handle as many user authentications as you require.
Make sure you don't use the client-side javascript SDK, which should not be used on the backend, but instead for frontend consumers like IoT, WebApps, Consumer Desktop Apps..
More info on the difference here: https://firebase.google.com/docs/admin/setup

Adding users to Firebase Database

I'm learning Firebase and creating my first project with it. I'm using FirebaseUI to simplify the authentication. I'm now working on the database and I need to start by adding my authenticated users to it. I've read all the documentation and I'm able to do this, but I'm wondering if I'm doing it the best way.
Since I'm using FirebaseUI and I'm not actually calling the signIn() or createUser() methods of Firebase Authentication myself, I thought the best way for me to add users would be to do it onAuthStateChanged()
usersRef = rootRef.child('users')
firebase.auth().onAuthStateChanged(user => {
if (user) {
let userRef = usersRef.child(user.uid)
userRef.set({
name: user.displayName,
email: user.email,
photoURL: user.photoURL,
emailVerified: user.emailVerified,
})
}
}
This works fine but I'm concerned about two things:
1) This sets the user data every time the user is authenticated, even if the user already exists and nothing has changed. A simple page reload will rewrite the user to the database.
2) In order for this to work, the userRef location needs to be writable by the user. This would mean that the emailVerified in the userRef location isn't reliable because the user could potentially modify it himself. I could just rely on the emailVerified returned from onAuthStateChanged which the user could never modify, but I'm wondering if I'm just doing this wrong or if there's a better way.
A possible solution is described in a video found at https://www.youtube.com/watch?v=QEd2lEoXpp40. He creates two sections in the database: users and loginQueue. A user in users is only readable by the authorized user and loginQueue is only writable by an authorized user. When a user is authenticated, his data gets written to the loginQueue. He then uses the on() method to check for a child added to the loginQueue that matches their user.uid and somehow uses the update method to write to the user data to users. This works but I don't understand how. How can is the client able to send an update() to users\uid if it's only readable? You can see his code at 7:00 in the video. This has me stumped. This works but why.
I just implemented the technique as shown in the video and although it worked for him, I encountered a PERMISSION_DENIED error when trying to update the only readable user data. This is what I thought SHOULD happen but in his video he clearly shows this was not happening. Unless I'm missing something which I don't think I am, his method doesn't work anymore. Maybe it was a bug that was later fixed?
UPDATE: Thanks to Doug Stevenson for pointing me to Firebase Cloud Functions. I was able to completely solve my problem by creating a cloud function that responds when new users are authenticated. Here is my code:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.addUserToDB = functions.auth.user().onCreate(event => {
admin.database().ref('/users/' + event.data.uid).set({
name: event.data.displayName,
email: event.data.email
});
});
This is a common strategy.
Authentication shouldn't happen too often. Also, if nothing changed in user record since the last write, nothing should actually happen. You don't pay for the bandwidth for client writes to the database.
Split your user data up into two sections, one that's writable by the current UID, and the other that's not. That will prevent problems with users modifying data that you'd not like them to.
Alternately to this, set aside another location in your database where your clients can push commands to update data elsewhere, and use a Cloud Functions for Firebase trigger to read these commands, act on them with elevated privilege, checking for correctness, and delete them.

Resources