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>
Related
Iam going to do an online library management system
I have **3 roles **(stored in separate tables in the database)
The user: they have an interface that displays all the books online so they can preview() the front of the books, search() the books and reserve() the books online
The librarian: they have a totally different interface that allows them to do the management (registering the users,adding/delete books/managing reservations..etc)
The admin : the one who have access to the whole database , and can manipulate it so for example if a librarian is fired he can omit them
My main question is about the authentication part
I said before that i have 3 roles (different tables in the database) , each one of them has a different interface
Is that type of authentication possible in the backend?
And in which framework/lang i can use?
I mean when the admin enters his email and pass , his own interface appears
And when the user enters his email and pass , the interface of books,reserving appears
And when the librarian open his email and pass , the management interface appears
Thanks in advancešš»
I didnāt start developing yet this question encountered me while designing the database, so i was worried about that concern
Because i am still studying the technology i will use nodejs/react so i was wondering of that type of authentication is possible?
It is totally possible. You can assign a role to each user that helps you point them to the correct interface when needed.
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.
IĀ“m currently developing an application based on user authentication where each user can register a student-campus as a teacher and currently, I'm on a feature where I have two routes:
Route 1: It has a Datagrid where I'm listing all of the student campuses that I've already created and each row has an edit button that navigates to "Route 2" and the purpose of that is to edit the already created student campus.
Route 2: It has a form with all the necessary fields to create a student-campus.
As you can see I need to pass the student-campus ID to fetch data in the ngOnInit to fill the fields and be able to edit the above-mentioned, so I have several options in consideration:
Option 1: Pass ID in the URL.
this.router.navigate(['planteles/registrar', idPlantel]);
https://myapplication/planteles/registrar/1
Option 2: Pass ID in the URL with queryParams.
this.router.navigate(['planteles/registrar'], { queryParams: { ID: idPlantel } });
https://myapplication/planteles/registrar?ID=1
Option 3: Pass ID in the state object of navigation extras.
this.router.navigate(['planteles/registrar'], { state: { id: idPlantel } });
Option 4: Shared service and BehaviorSubject to subscribe to data.
I owe you the code
I'm able to use any of these but I have a problem with each one of them.
I can't use Option 1 and Option 2 because the ID cannot be changed by the teacher because that gives him the possibility to fetch the student-campus data of another teacher and edit it, so it isn't safe.
The problem with option 3 and option 4 is when I refresh the page the state is lost.
Currently, I have a workaround with option 3 which is to redirect the user to the previous page if the state is undefined but I don't like that solution. I'd like to persist data if the user reloads the page without using LocalStorage.
Thanks in advance, all help or contribution is well appreciated.
Option 1 is the correct option here (and the way you will find most sites in the real world are implemented... including this one we're on now). The problem is your approach to web security, and what you need to fix is your backend. You're approaching web security as though front end security is real, it's not. Web security exists on your backend. Users should not be able to fetch or view or manipulate data that does not belong to them, and this must be enforced by your backend.
A high level example of how this might work: some secure authentication token should be granted when the user logs in, then this authentication token should be attached to each request. The API then uses this token to check which user is making the request and ensures they have the proper permissions. If they do not (as in the case of the user editing their URL param to some ID they do not have permissions for) or if there is no token, the API should return a 401 or 403 response and the front end should handle it appropriately (ie sending them back to list, or showing an error page, whatever you decide)... how to issue this token, make it secure, and make use of it is an entirely separate topic beyond the scope of this answer.
In any of the options, I could open my dev tools, and view any API requests being made, and change the ID's and use that to view or manipulate other people's data without any effort at all. So options 3 / 4 are barely more "safe" than 1 or 2. As none of these are safe without properly implemented backend security.
Front end "security" exists only as user experience. Me and you are both using the same URL to view this page, but we see different options and buttons, like you can edit or delete your post and accept answers, while I can't, but I can edit or delete my answer etc. This isn't for true security purposes, SO's servers enforce who can and can't take what actions. It's just showing me and you the UI that reflects our different permissions, ie, its all just UX.
There's another way too, which is defined in Angular docs itself.
NavigationExtras
Example:
let navigationExtras: NavigationExtras = {
queryParams: {
"firstname": "Nic",
"lastname": "Raboy"
}
};
this.router.navigate(["page2"], navigationExtras);
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I am using MongoDB over a Node.js backend API. Works awesome.
When user inserts a new post, I want to update it's followers, it's followers are not officially listed as followers in a collection of followers, they are just potential users to be likely like his post.
For example, if one writes a post in some city that other marked as a key city, this post should be in his notification feed.
In order to do that, the Node.js backend API has to check each user if he has in his key cities the city that the poster posted.
If then, its should make another MongoDB query, which is inserting the notification, so it will be listen in the followers notifications feed.
And also, push a mobile app notification.
I know it has to be sliced into pieces, therefore I made the poster to only post his post, then to emit a socket to the server, telling that there some data need to be processed.
The server listens to the socket emit and starts finding and inserting the notification to the right places in DB.
After, the server runs another function sending push notifications via Google Firebase Cloud.
But I wonder, because now it works just perfect, if the same will be when the server should do that task for huge amount of rows, not just 5k users..
Info about the ingredients of my project:
Node.js, MongoDB, AngularJS and Express.
This is efficiency question, so I thought it will be wise to not bother you with ton of lines of code.
Thanks.
This may not be a scalable solution. An insert in one collection triggering a query to another collection that inserts subdocuments into an array is going to be a very heavy operation once you get a large number of users.
I would recommend having 3 collections to handle this task. One collection is for posts. One collection is for cities. And one collection is for users. Rather than inserting notifications to the user collection, insert the notifications into the cities collection. Each city will hold an array of notifications relevant to that city. Users can hold an array that holds their cities of interest that is used to pull in notifications from the cities collection. By setting it up this way, you are only updating one document with each post upload, instead of potentially a large number.
ex.
Post {title: 'my awesome post', url: 'awesomeurl.com'}
City {name: 'Los Angeles', state: 'CA', notifications: [{postTitle: 'my awesome post', url: 'awesomeurl.com'}, {postTitle: 'my lame post', url: 'lameurl.com'}]
User {firstName: 'raz', citiesOfInterest: ['Los Angeles', 'Denver']}
Note: This example could reduce data redundancy to be more efficient, but is left this way for readability.
Another benefit of not updating the user object is that it allows indexing of the cities of interest by each user. If a mobile push notification needs to go out to all users interested in 'Los Angeles,' an index will make this quick work (instead of an intensive operation that requires reading and possibly editing each object).
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I want to create more than 1000 users at a time by using
createUserWithEmailAndPassword api.But after 10-15 users created successfully,I got the error message that firebase block this device due to some unusal activity.
As per my understanding,this is because,whenever i am creating user ,user automatically login due to which from a single device multiple user login,firebase blocked the user.
Will there any ways to solve this problem.Please suggest me how to create more than 1000 users.
Will there any ways to use old sdk in new sdk in firebase.In old version firebase api,it is working fine.
Update (2016-11-08), original answer below:
Firebase just updated their command line tools and added an auth:import command:
The auth:import command imports user accounts into a Firebase project.
See the reference documentation for auth:import to learn more about it.
There now also is a Firebase Admin SDK, which contains functionality that you can run on a server to create user accounts without immediately signing them in. This SDK is still under a rate limiting though, so you'll probably be better served by the auth:import command of the CLI.
Original answer
The current Firebase Authentication API is made to allow users to create their own account. It is not meant to allow pre-creating accounts by some administrative process. As you've discovered, such a process will quickly be blocked.
There is no way to accomplish your use-case at the moment, aside from creating the accounts when the user actually signs up. We may expand the API in the future to allow you use-case, but as usual: no promises or timelines.
Try to logout user after it has been successfully created and before you make call of another user creation.
Try the following code. I have not tested it but it should work. If it does not try in increase timeout delay.
var userArray = [
{
email: "...",
password: "..."
},
...
];
createUser(userArray, 0);
function createUser(array, index){
if (index >= array.length){
return;
}
var user = array[index];
firebase.auth()
.createUserWithEmailAndPassword(user.email, user.password)
.then(function(){
setTimeout(function(){
firebase.auth().signOut().then(function(){
// Call to create new user
createUser(array, index + 1);
});
}, 100);
});
}
[Updated]
I think firebase does not allow to be signed in with multiple users so when you call firebase.auth().createUserWithEmailAndPassword it should replace existing user with new one.
Try to set an observer on current user and see if it changes when you call createUserWithEmailAndPassword method.
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
} else {
// No user is signed in.
}
});
For more info about managing the users check the following link.
https://firebase.google.com/docs/auth/web/manage-users