Firebase Authentication (multiple types of users) - reactjs

i am working on a react.js project which authenticate from firebase but i have 3 multiple type of user's in it (super Admin,vendor admin,vendor staff) with different privileges. how can i authenticate them from firebase and get to know this is my venor admin or vendor staff etc ???? because firebase just authenticate single type of user!

You can control access via custom claims using the Firebase Admin SDK on your own server of through Cloud Functions for Firebase.
Set claims server side for a specific bid with a method like this:
admin.auth().setCustomUserClaims(uid, {admin: true}).then(() => {
// The new custom claims will propagate to the user's ID token the
// next time a new one is issued.
});
Then set up your database with a structure that separates admin and vendor admin content:
/
/admin
/data for admins here
/vendorAdmin
/ data for vendor admins here
/staff
// data for staff here, or perhaps this data is accessible to all since the admins may need access to it.
In the Firebase Console, customize the rules to restrict these locations to those who include the proper claim:
{
"rules": {
"admin": {
".read": "auth.token.admin === true",
".write": "auth.token.admin === true",
}
"vendorAdmin": {
".read": "auth.token.vendoradmin === true",
".write": "auth.token.vendoradmin === true",
}
"staff": {
".read": "auth.token.staff === true",
".write": "auth.token.staff === true",
}
}
}
This is a simplified example, so you'll have to customize it further to meet the needs of your app.

You can maintain a users table in your database, and every time you sign up a user just add them there as well, using the uid.

Related

enable and disable users firebase auth reactjs error

I have 2 separate platforms I use the same firebase confing for both of them
The first one is for the normal users , they can register and login and see the courses.
The second one is for the admins (ps: the admin is like a normal user , but I have a special collection called admins for the admin and another one called users for the normal users )
To check if the person who logged in is an admin , I check if his email exists in the admins collection).
So in the admin platform I should display a list of users
I want to enable and disable a spisific user (I can get his document Id, and UID)
when i use :
try {
await getAuth().updateUser(uid, { disabled: true })
getUsers()
} catch (error) {
console.log(`is error of ${uid} with ${error.message}`)
}
i got this erroe:
firebase_auth__WEBPACK_IMPORTED_MODULE_1__.getAuth)(...).updateUser is not a function

Adding extra information to registration user Firebase

I would like to make an application in React Native that allows to work in two modes, parent and child. The initial stage is registration with Firebase, then after adding additional information about the role (parent / child), registering both the child and parent, and after logging in both of them, the child will share location and parent will receive it.
I would like to add additional fields such as role (parent / child) in my application in React Native + Firebase, to later create other functionalities of the application based on the role.
Registration:
firebase
.auth()
.createUserWithEmailAndPassword(email, password)
.then(userCredentials => {
return userCredentials
.user.updateProfile({
displayName: name,
})
.additionalUserInfo.profile = {
role: role,
}
})
Homescreen
const { displayName } = firebase.auth().currentUser;
const { role } = firebase.additionalUserInfo.profile;
this.setState({displayName, role});
and role returns undefined.
The properties that you can store on a user profile are defined by Firebase Authentication. You can't just add additional properties to it as you see fit. At best Firebase will simply ignore those, but likely it will also explicitly reject them (throwing an error).
If you want to store additional information about a user, you have two main options:
Store the additional information as custom claims in the user's authentication token.
Store the additional information in an external database, such as the Firestore and Realtime Database that are part of Firebase.
While storing the data as custom claims is pretty close to what you want to accomplish, you'll need to keep a few things in mind:
Custom claims are used for authorization purposes, and for that reason can only be set from a trusted environment (such as your development machine, a server you control, or Cloud Functions). So you can't simply set the role from within the app, and will need a separate process to add that claim.
After setting a custom claim on a user profile it may take up to an hour before that change is visible in the client. If you need it sooner, you can force the user to sign in again, or refresh their ID token.
Custom claims are sent with every request you make to Firebase resources, and for that reason are very limited in size. There's a maximum size of 1000 bytes for custom claims for a user. While your current role will easily fit into that, it may limit what you can add later.
If instead you store user data in an external database, you'll typically combine it with other information about that user into a users node/collection. In here you'd store a document/node for each user based on that user's UID, and then their profile information.
So something like:
users: {
uidOfAleksandra: {
username: "Aleksandra",
displayName: "Aleksandra Lastname",
role: "parent",
registrationDate: "2020-02-01"
},
uidOfPuf: {
username: "puf",
displayName: "Frank van Puffelen",
role: "child",
registrationDate: "2015-03-07"
},
}
Having this list of user profiles does not only allow you to store the additional information for each user, but would also allow you to query that list of users from within your app, something that the Authentication API doesn't allow from within application code.

How to prevent customers from modifying firebase data (in web-application without backend)?

I've recently starting exploring firebase as a authentication solution for my angular JS single-page website, and it seems perfect. However from a security perspective I'm not very sure about keeping the logic on client-side in my application.
Suppose I have a check 'isProfileCompleted' for a customer who signs-up on my website, and is supposed to complete his profile. I'm keeping the data in a JSON keyed by the UID with exclusive write access to the customer only.
The problem is, now that the client has write access to his data, he can easily bypass client side validation checks by simply modifying javascript in his browser. Also, the client can easily update his account_type to author/moderator, as it's his data. Does firebase provide a solution to this problem?
Let me know if it's not clear, so I will try to elaborate further.
Thanks.
You can secure your data with Security Rules.
Firebase Security Rules are an expression (does the true evaluate to true/false) based rules language that live on a Firebase server and validate whether the current user can access your data.
Take the following data structure:
{
// the users of the app
"users": {
"1": {
"name": "Sanjay",
"isProfileCompleted": true
},
"2": {
"name": "David",
"isProfileCompleted": false
}
}
}
By default anyone can read or write data to your Firebase database. To fix this you can write security rules.
Security Rules are essentially an annotation on your data structure:
{
"rules": {
"users": { // /users is read only
".read": true,
".write": false
}
}
}
Security Rules give you access to a set of server variables to check your rules against. The most commonly used one is the auth variable which lets you check against the currently authenticated user. You can also create wildcard variables with the $, which acts a route parameter creating.
{
"rules": {
"users": {
// users can read and write their own data, but no one else.
"$uid": {
".read": "auth.uid == $uid",
".write": "auth.uid == $uid"
}
}
}
}
You can even write rules to validate the structure of your data.
{
"rules": {
"users": {
// users can read and write their own data, but no one else.
"$uid": {
".read": "auth.uid == $uid",
".write": "auth.uid == $uid",
".validate": "newData.hasChildren(['name', 'isProfileCompleted']),
"name": {
".validate": "newData.isString()"
},
"isProfileCompleted": {
".validate": "newData.isBoolean()"
}
}
}
}
}
But the Bolt compiler is a better solution for this, as it allows you to create Types to define schema.
You can write your Security Rules in the Firebase App Dashboard or you can upload them via the Firebase CLI.

Securing system-generated nodes in firebase

I've been going through the rules guide but haven't found an answer to this.
App users are able to submit "scores" of different types, which are then processed in JS and written to a "ranking" node. I have it set up so that every time a new score is submitted, the rankings are automatically recalculated and a new child is written if the user doesn't exist or updated if the user exists.
My question is how to secure this "ranking" node. Everyone should be able to read it, nobody except the system should be able to write it. This would prevent people from submitting their own rankings and aggregate scores.
EDIT
This is the operation:
Ref.child('rankings').child(uid).once('value', function (snapshot) {
if (snapshot.exists()) {
snapshot.ref().update(user); //user object created upstream
} else {
var payload = {};
payload[uid] = user;
snapshot.ref().parent().update(payload);
}
});
How would I add custom authentication to this call? Also, since I'm using AngularJS, is there any way to hide this custom token or would I have to route it through a backend server?
The key part of your problem definition is:
only the system should be able to write it.
This requires that you are able to recognize "the system" in your security rules. Since Firebase security is user-based, you'll have to make your "system" into a user. You can do this by either recording the uid from a regular user account or by minting a custom token for your "system".
Once you have that, the security for your ranking node becomes:
".read": true,
".write": "auth.uid == 'thesystem'"
In the above I assume you mint a custom token and specify thesystem as the uid.

If I use $firebaseAuth.$createUser will that populate the auth variable for security rules?

I am using the $firebaseAuth.$createUser() method to register a user to my firebase backend, I then immediately try to create a /profile/ for the user. In 'profile' security rules I have rule that only the current user can create/edit their profile.
"profile": {
".read": true,
"$profileId":{
".write": "auth.uid == $profileId"
}
}
However it appears because I do this right after I call $createUser() using the then() chainining method that the auth variable isn't correct when the security rules process. Do I need to call an auth() method or something after I call $createUser() ??
Ok, after digging through the documentation, I found that $createUser() does NOT authenticate the user. Once the account is created, the user may be authenticated with the authWithPassword() function.

Resources