Wondering about security with MongoDB with Firebase and Flutter - mongodb

So im using Firebase to authenticate a user and that works fine. In the end I get a uid, which I can uniquely identify a user. I dont want to use any other firebase tools since I dont believe they are suited for my application, so I want to use mongoDB for document storage. I can thus use the uid as the key to the person ( and other ) data.
My question is about security. What is someone gets access to the uid? and since this uid might link to other user's uid, if someone gets access, then they might be able to just call a collection.get on any uid and get potentially user sensitive data. How do I prevent this interaction? Am I overthinking this and mongo somehow handles this? Im not quite sure how to authorize that the current user is the current uid and hes not calling any document retrieval that is not allowed. Thanks

A UID merely identifies a user. You should never use a UID as an authentication mechanism, but instead require that the user enters the required credentials that then lead them to get the same UID. See also my answer on Firebase - Is auth.uid a shared secret?
If you're accessing MongoDB from a server, you'll typically:
Sign the user in on the client-side app.
Get their ID token and pass that token to your server over a secure connection.
Verify the ID token on the server using a Firebase Admin SDK, or other library.
Then determine what data the user is authorized based on their UID or other properties/claims from their ID token.
This process is pretty well documented in the Firebase docs on verifying ID tokens.

Related

Next-auth (JWT) logging sessions

According to Next-auth documentation as we are using credentials provider to connect to our users collection for usernames and passwords Next-Auth does not use the session database to check if a session is active.
If you use a custom credentials provider user accounts will not be persisted in a database by NextAuth.js (even if one is configured). The option to use JSON Web Tokens for session tokens (which allow sign in without using a session database) must be enabled to use a custom credentials provider.
I am wanting to add a _middleware that will allow me to store and check that the latest JWT sessions inside our session database matches the latest one that the user is currently using.
Reason being is that if I have two devices technically I would be able to login on both devices and at the moment their is no real way to discern if the user from PC2 is also login on PC1.
So my theory and not sure if this will work is to add the following.
callbacks: {
jwt: async ({ token, user }) => {
console.log("running JWT - because of custom login")
user && (token.user = user)
(ADD CODE HERE TO SAVE TOKEN & CHECK IF TOKEN IS LATEST TOKEN + VALID - INSIDE SESSION DATABASE)
(IF OLD-TOKEN IS NO LONGER VALID OR THE LATEST TOKEN LOG THE USER OUT)
console.log("TOKEN IS "+ JSON.stringify(token))
return token
},
session: async ({ session, token, user }) => {
console.log(JSON.stringify(session) +" / "+ JSON.stringify(token) +"/"+ JSON.stringify(user));
session.user.tokenID = token //ADD CODE HERE TO SAVE TOKEN TO SESSION COOKIE
session.user = user
return session
}
},
Then if I create a middleware that checks this tokenID and matches it with the session database and if it is the latest result from said user.
For example.
Say PC1 (user1) login here
{
_id: 1
tokenID: 918171-918171-81716-0887
userid: 00-00-00-001
expire: "2022-05-23T12:47:04.593Z"
}
But then PC2 also (user1) login again and created a new session
{
_id: 2
tokenID: 71888-651777-616666-0117
userid: 00-00-00-001
expire: "2022-05-24T12:47:04.593Z"
}
What I would need the middleware to do (which a simple mongodb query could do) is check if their is an older session stored for the same userID if so then logout from PC1.
Now there are a few things that I can see going wrong with this idea.
Other Provider Sessions (which use session DB) making it harder to validate
Every time you call the signup page or session it seems to re-run the JWT section - which in theory is fine, as we could use a findOne Update function which if token is in session then just update the expiry - however that would cause say PC1 refreshes after PC2 logged in then PC1 expire time might be longer then PC2 expire time (but a simple sort function would allow us to see if the ID was older then PC2 if so logout).
JWT changes token every time you reload the page
How would this help privacy and the user data?
By not storing the user details inside a session cookie we would not be exposing the data to hackers or other plugins like FB or Google as the user data would only be linked to a token ID. Which to request the user data you would have to make sure the tokenID was valid first and then be allowed to fetch user data.
I understand that Next-Auth may not want too do this, and this is why I ask the question what is the best practice to do what I am wanting to achieve.
This answer is based on the confirmation that the issue is that you want to be able to only have users able to be signed in to one computer/device at time and that you are using usernames and passwords to authenticate them.
In that scenario you also need to have a database that records a token in each JWT issued. It is not possible to solve for that problem without a database.
Here is how you can solve for it it using JWT and a database:
On every new sign in, you would need to use the jwt callback to add something like a UUID to each JWT and then record that UUID , the User ID and the time the JWT expires in a database.
In that callback, if there are other entries in the database for the same User ID you should mark them as invalid (or delete them from the database).
Everytime an existing JWT is read in that same callback you would need to check to see if the UUID in the database was still valid (i.e. still exist / doesn't point to a UUID that corresponds to a JWT flagged as expired) and if it is no longer valid, don't return a valid JWT.
You might also want to add special handling in the session callback that does something similar to improve the user experience by gracefully handling it in the User Interface of the computer they are being signed out of.
Effectively this has all the downsides of a JWT with all the downsides of a session database (although there are niche cases where this is a preferable approach).
I would not recommend using usernames and passwords or limiting users to only being able to sign in to one computer at at time, however given those unusually specific constraints (which also necessitates a solution that has a negative impact on performance) you may want to consider a different authentication solution and/or think how else you could address the underlying need this is trying to address (and if it's worth the cost and complexity).

Limit user access to api calls?

I am creating a rest api to be the backend for a messaging app. I want a user to only have access to their own data. For example user1 can call /users/user1 but not /users/user2. How would I go about doing this.
So first the user will login and be authenticated via their username and password. But where do I go from here? I was thinking of storing a token with the users data so when they access it I can verify that the pair matches but there must be a better way to do this. Do I need to restructure my api?
After the user logs into the system, you should provide them a token or initialize a session for that user. In each consecutive call, the user should send the token to the API. As long as the token/session is alive user should be able to call the API.
You should have a way to verify the user token in the backend for each API call. A very popular way of doing this is to use JWT(JSON Web Tokens) based authentication.
See here for an example using python and flask: https://realpython.com/token-based-authentication-with-flask/
Once you verify the user, you should parse the user id to the database query in order to filter out the data for that user.
Even though I don't understand your full use case, it seems like you need to restructure your API calls as well. You should not provide API calls per user. What happens when the numbers of users increase in your system dynamically?
So you should either accept user id as a parameter or you should let the JWT authenticator take care of it.
Example REST API call would be
GET /user/data?userId=1234

Correct workflow of a REST API for mobile app authentication

I am in the process of building a REST API for mobile app developers to be used on a web application built using Zend framework. My first task is to create a service for authentication/authorization. I have read lots of related questions here on SO and would like to sum up what I am doing:
There is no session or cookie involved, so a typical web app method
of checking the logged in state of the user doesn't work here.
With each login request, the username and password is received and a
random string is generated and saved in the DB against the username.
Also, this string is returned with the authentication request.
This user token is sent along with any request that needs authentication.This token is matched against the stored value in DB and if matched, only then the user is allowed to perform the required task.
On logout, the token value in the DB is reset to blank or NULL.
Is this the correct approach ? Won't it over load the DB because with each request, a select query is run on the DB to check for the token value ? If you could provide any tutorial link, that'd be much appreciated.

Facebooks Thid-Party-ID - How to use it

For my facebook app i need to store user-records on the server side. Because the data should be anonymized i don't want to store the user-id. I found out that the third-party-id should be what i'm looking for (user can request his data but it's not possible to get the user based on the data).
But now my Questions regarding the third-party-id:
The id seem to be dependend on the used access token. But when i use the user-access token (which expires) will the third-party-id change when the user gets a new token?
Is it common to received it via an app-access-token?
I tried it in the graph-api-explorer where I was able to find users based on the third-party-id. Why is this possible and how can I prevent it?
Thanks in advance
No the third party ID is not dependent to your access token. The user access token is a temporary key that allow access to permanent data, such as the name, or the third party ID.
By the way you can test it yourself by generating a third pary ID on your account for your App, record both the ID and the token used to get it, uninstall your own app via the page http://www.facebook.com/appcenter/my , and finally reinstall your App. You will see a new token ginving access to the same old ID.
I don't understand what you mean by receiving it via an app-access-token. App access tocken do not give access to users' data.
Finally, you don not have to do anything to prevent it. Facebook got you covered. While using the third party ID instead of the user ID is a good idea for extra security, the third party ID has been introduced for cases where your Facebook unique identifier is not totally invisible.
You were able to find a user based on his third party ID because you own the Facebook App that generated this ID. A user has as much third party ID that he has installed App, and they are all different and only only works with the App that generated it. So your server side user record is safe because the IDs it contains would not be of any use to something else than your app.

Identifying/Managing users based on session ID (Mapping between Session ID to User ID to User Data)

I wrote a web-app that authenticated a user via Facebook connect (o-Auth).
After the user have authenticated I have a facebook token.
Using this token I send a request to Facebook to grab its basic user information.
At this point I have the user unique Facebook id and I know who it is.
How should I link between the user, the token and it's data in the database?
Right now my schema is pretty simple: facebook_id is the Primary key, and there are some other columns that includes the token and the user's data. Is that the correct way to do it?
At which point do I need to set a unique SESSION_ID (cookie) on the user request? After it authenticated?
I am confused about this part (and with Session management in general). When i set an attribute on a session does the browser remember it an send it in every request to my server? across all pages?
And the most important question is, how do i map between the SESSION ID and the user? Once i set a session id on his request, i need to figure out on every request who it is. What's the best way to do it?
That is fine, all you really want to do is to be able to match to a particular Facebook User ID with the data created by or in your web app that doesn't come from the Graph API .
At the moment you complete the Login flow (when you receive the Access Token). When you set a session the browser will remember the key-value pair in it until the session is cleared. So you want your code to be able to associate someone using a browser with a particular user in your database (or not if they don't have a session). Thus, whatever session value you use, you need to also store this in the Database alongside the User ID.
See above.
Honestly though, the very easiest way of doing this is to just use the Facebook Javascript SDK. This will handle all the access token retrieval and user persistence through cookies automatically, without you having to write code for it. Ultimately this will mean that all you need to do is store the Facebook User ID in your database alongside the app-generated content and won't need to worry about storing access tokens or session variables. There's a simple step-by-step guide here:
https://developers.facebook.com/docs/howtos/login/getting-started/
(in Step 5 you'll receive the User ID and you can make an AJAX call to server-side code from here to store it in your database)