This question already has an answer here:
Firebase security rules to check unique value of a child #AskFirebase
(1 answer)
Closed 2 years ago.
I am using Firebase Web SDK in my project. At the moment I am creating a simple mailing list sign up form. I am trying to check that no duplicate emails get signed up. At the moment, it is possible to do this as firebase creates a message id one level up from the data being stored and I do not know how to validate it.
Here is my code:
db.ref("/signup_emails").push({
name: d.name,
email: d.email
}
Whenever this creates an entry into the database it does so with a message_id. Like so"
signup_emails {
- M1itOVYTq-ySh_49rH3 {
name: "John"
email: "example#example.com"
}
}
How do I validate that the email has only been signed up once?
As you have things structured now, it is not possible with Firebase security rules. If you want to know if there's child node with a specific value, and you don't know its full path, you would have to perform a query to find it. However, security rules don't have the ability to perform a query. You can only reference a node by its fully specified path.
If you want to use security rules to find a piece of data, that data will have to be the name of a node that contains that data. So, the email address, or some form of it, will have to be in the path, not in a value.
Or, you can push the logic into backend code that can perform the check for you.
Related
I have a custom claim "admin" attached to each user, carrying a boolean.
Now, in my frontend i am trying to generate a list of all admins.
For that i need to access all users who have said custom claim set to "true" and put them in an array, which i can then generate the list from.
The array should just look like the following:
const admins = ref([
{
uid: *uid of admin1*,
name: *name of admin1*,
},
{
uid: *uid of admin2*,
name: *name of admin2*,
},
...
])
So the following problems arise:
How do i access all users with said custom claim set to true, so that i can loop over them and populate my array?
Is this a case for a cloud function, so that it can not be manipulated?
I tried reading this Firebase documentation, however i could not make sense of it.
How do i access all users with said custom claim set to true, so that i can loop over them and populate my array?
There is no direct way to query users based on custom claims.
Is this a case for a cloud function?
Yes, you would have to list all users as in the documentation that you've shared and check for custom claims for each user separately.
It might be best to use a database like Firestore or Realtime Database and maintain a collection of all admins. Make sure this cannot be updated from client side directly using security rules.
I am using the Firebase 9 JavaScript Web SDK and I want to get the date/time of the last user password update.
Is that possible? And how is it done?
I can't find anything in the docs.
I don't see any value indicating the last password change timestamp in the relevant Firebase objects that I know of (User, UserCredential, UserInfo, UserMetadata). So it seems this information is not available in the API, and you'll need to track it yourself.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I have users and projects in a web application. Each user can have n projects. Each project can have m users. From a DB point of view, there are three tables: user, project, and user2project (to map the user and project n:m relation).
The backend is a simple crud-rest api (relational). Furthermore I'm using a JWT-token based authentication.
My frontend would show a project via projectId:
localhost:4300/projects/941343/
If the shown project belongs to the currently logged in user, my frontend should show additional buttons, such as "edit project".
But how can I know, that this project belongs to the currently logged in user?
Idea 1:
Have my backend always return the userids when the project is returned.
Sample response:
{
projectid: "941343",
title: "Some Project-Title",
description "Some Project-Description",
user2project: [
{ userid: "902319" },
{ userid: "299322" },
{ userid: "920392" }
]
}
With this approach I would just check if the project-object holds a user2project-object with the same userid as the currently logged in user.
Disadvantage: additional join in backend and bigger payload
Idea 2:
Once a user is logged in, I would persist not only the UserId, but also all ProjectIds of that user.
As such, I could then simply check the ID of the url with the persisted data.
Disadvantage: whenever someone else adds my user to a project, that change is not registered until I log in again.
Question: are these ideas viable for this purpose? Is there a better approach even?
If you know both the user id and the project id, the you could see whether or not this SQL query returns any result:
SELECT * WHERE user_id=X AND project_id=Y
You do the check on the server side. To check the same from the client side, you create an API call for it.
If the shown project belongs to the currently logged in user, my frontend should show additional buttons, such as "edit project".
I originally misread your question, I feel others may have also.
Using the authenticated user, check if the authenticated user === project owner inside your component, this could be as simple as:
<div *ngIf="authenticatedUser.id === project.ownerId">
<!-- SHOW BUTTONS -->
</div>
You would do this inside your ProjectSingleComponent, or whatever it's named inside your app.
If you support multiple users with the option to make changes, then use an .includes instead, checking if the array includes the authenticated user.
This is something RBAC would help with (not the buttons, practice in general). I'd encourage taking a look at what that would entail for future reference (although this is now off-topic to your original question).
EDIT: If you are looking to securely manage who has access to what, then this is the role of authorization and should be implemented using permissions, plus an additonal layer of database isolation (either physically or logically), to truly prevent access. If it's only the buttons you're interested in, the above approach may work.
An example to reflect my comment:
<div *ngIf="project.owners.includes(authenticatedUser.id)">
<!-- SHOW BUTTONS -->
</div>
This question already has answers here:
stop Firestore warning that everyone can read data
(1 answer)
Your Cloud Firestore database has insecure: any user can read your entire database
(2 answers)
Closed 2 years ago.
I am new to firebase, and am a bit stuck with the rules.
My app is essentially a blog-site.
It allows non-logged in to read posts, users, comments.
It also allows logged-in and verified users to create a post.
Here are my rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read: if true;
allow write: if request.auth.uid != null;
}
}
}
Firebase sends me emails that these are not secure due to "any user can read your entire database".
Is there something I am missing? As I want people to be able to read the data without being logged in?
I believe you're still getting that due to, based on the "if true" logic, any user has the ability to read anyone else's "stuff." What you could do is add some functions within the match database documents that return more tailored tests. You really want to avoid an open database in Firestore, so part of that is by design, in-terms of that e-mail you're getting. I went through this same issue myself, and ended up moving over to Mongo for that particular use case.
However, if you want to keep it open, you can turn off the alert emails from the console. Click on Firebase alerts in the top-right, click settings (gear), select your project, just choose which you want to receive. I know those alerts can get annoying, haha, but it's Google's way of trying to help :) good luck!
Firebase prefers that you call out each collection individually in your security rules to allow access, rather than use a wildcard to match everything. They have no way of knowing if you actually have some private data in a collection and are accidentally giving access to it. By specifying rules for each collection separately, you are being very clear and specific about the access for each one of them.
This question already has answers here:
How to protect firebase Cloud Function HTTP endpoint to allow only Firebase authenticated users?
(9 answers)
Closed 5 years ago.
I am trying to figure out if it is possible to check auth object from client that called firebase https cloud function to achive following tasks:
1) Only allow authed users with verified email call https endpoint, otherwise return 403.
2) Somehow gain access to uid of client that called a function in order to set node like characters/:uid in database.
Reason for this is to disallow duplicate characters. I can manually pass uid in req.body, but this means that anyone could fiddle with this and create 100 different characters by sending any sort of uid as req.body payload.
Only work around I can think of for this is changing this logic to database triggers i.e. client writes to database void/characters/uid node (database rules do this whole validation) then function listens to this change in database, processes data and pushes it to characters/uid
But this means additional logic like removing node after it is done is needed, plus I am not sure how to send back error or success response back to client, as with https functions we can just res.send(200) or send back error.
If I understand this, I think this can be done by firebase rules.
https://firebase.google.com/docs/reference/security/database/#location
In the example provided, a rule like :
".write": "auth.uid === $user"
Would only allow authenticated users with the same uid as appears on the path to write data there.
I am uncertain if a 403 is returned. This implies that you are using firebase authentication, which is covered in some depth here, depending on the mechanism you are using for authentication.