I\'m building a website where I\'ve integrated firebase authentication for login/signup of site users.
Users can login/signup via either email-password or mobile OTP
First signup and onComplete
method check if signup is successful.
if (task.isSuccessful()) {
// String userId = task.getResult().getUser().getUid();
// get user unique id
// saveUserData()
}
get user unique id and use it as key and store data like
applicationName->usersNode->userId->data
check if data is stored successfully proceed to next activity or Home page else remove user from auth and ask him to retry again.
Since you want to save a user's data. I assume you are saving the data to be able to do some operations on it later. Thus it is advisable you should save your data in cloud firestore. Cloud Firestore's queries will help you in the future to be able to manipulate any CRUD operations that you may want on the data.
A good way of storing the data is after registering the user with firebase auth. You can take the userID returned by firebase auth in the oncomplete listener, then take make a document with its key being the userID inside your USERS collection,then you save the extra information about the user in that document.
This is something that every firebase user has to deal with. How is generally solved? As other users point out, it is solved by adding the extra user information into Firestore. Can you guarantee that atomiticy? No, you can't, auth and db are two different systems, you can add the user to auth and in the callback find out you cannot add the user to db because you dont have internet connection for instance. What people do? Generally live with it.
If it is fundamental for your application to guarantee atomiticy you can go an extra mile and implement your authentication in a firebase function. For instance, this is an example of a two step sign in:
import { Request, Response } from "express";
import * as admin from 'firebase-admin'
export async function create(req: Request, res: Response) {
try {
const { displayName, password, email, role } = req.body
if (!displayName || !password || !email || !role) {
return res.status(400).send({ message: 'Missing fields' })
}
const { uid } = await admin.auth().createUser({
displayName,
password,
email
})
await admin.auth().setCustomUserClaims(uid, { role })
return res.status(201).send({ uid })
} catch (err) {
return handleError(res, err)
}
}
function handleError(res: Response, err: any) {
return res.status(500).send({ message: `${err.code} - ${err.message}` });
}
You could add the user removal from auth if something goes wrong. This guarantees at least that your rollback code will be executed in the Google servers.
This code example was extracted from https://www.toptal.com/firebase/role-based-firebase-authentication
The additional information you want to capture would indeed usually be stored in an additional database, such as Cloud Firestore or the Realtime Database. Custom claims are typically reserved for information related to access control, such as group membership and whether the user is an admin.
There is no atomic way to add additional information during sign-up beyond the minimal information that is needed for the sign-up (i.e. the email address and password when using email+password authentication). If atomicity is a requirement for your use-case, you may want to look beyond Firebase.