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

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)

Related

Wondering about security with MongoDB with Firebase and Flutter

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.

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

Possible approach to secure a Rest API endpoints using Facebook OAuth

I've been reading a lot about the topic but all I find are obsolete or partial answers, which don't really help me that much and actually just confused me more.
I'm writing a Rest API (Node+Express+MongoDB) that is accessed by a web app (hosted on the same domain than the API) and an Android app.
I want the API to be accessed only by my applications and only by authorized users.
I also want the users to be able to signup and login only using their Facebook account, and I need to be able to access some basic info like name, profile pic and email.
A possible scenario that I have in mind is:
The user logs-in on the web app using Facebook, the app is granted
permission to access the user Facebook information and receives an
access token.
The web app asks the API to confirm that this user
is actually registered on our system, sending the email and the
token received by Facebook.
The API verifies that the user
exists, it stores into the DB (or Redis) the username, the token and
a timestamp and then goes back to the client app.
Each time the
client app hits one of the API endpoint, it will have to provide the
username and the token, other than other info.
The API each time
verifies that the provided pair username/token matches the most
recent pair username/token stored into the DB (using the timestamp
to order), and that no more than 1 hour has passed since we stored
these info (again using the timestamp). If that's the case, the API
will process the request, otherwise will issue a 401 Unauthorized
response.
Does this make sense?
Does this approach have any macroscopic security hole that I'm missing?
One problem I see using MongoDB to store these info is that the collection will quickly become bloated with old tokens.
In this sense I think it would be best to use Redis with an expire policy of 1 hour so that old info will be automatically removed by Redis.
I think the better solution would be this:
Login via Facebook
Pass the Facebook AccessToken to the server (over SSL for the
android app, and for the web app just have it redirect to an API endpoint
after FB login)
Check the fb_access_token given, make sure its valid. Get user_id,email and cross-reference this with existing users to
see if its a new or old one.
Now, create a random, separate api_access_token that you give back to the webapp and android app. If you need Facebook for
anything other than login, store that fb_access_token and in your
DB associate it with the new api_access_token and your user_id.
For every call hereafter, send api_access_token to authenticate it. If you need the fb_access_token for getting more info, you can
do so by retrieving it from the DB.
In summary: Whenever you can, avoid passing the fb_access_token. If the api_access_token is compromised, you have more control to see who the attacker is, what they're doing etc than if they were to get ahold of the fb_access_token. You also have more control over settings an expiration date, extending fb_access_tokens, etc
Just make sure whenever you pass a access_token of any sort via HTTP, use SSL.
I know I'm late to the party, but I'd like to add a visual representation of this process as I'm dealing with this problem right now (specifically in dealing with the communication between the mobile app and the web api by securing it with a 3rd party provider like facebook).
For simplicity, I haven't included error checks, this is mostly just to outline a reasonable approach. Also for simplicity, I haven't included Tommy's suggestion to only pass your own custom api token once the authorization flow is over, although I agree that this is probably a good approach.
Please feel free to criticize this approach though, and I'll update as necessary.
Also, in this scenario, "My App" refers to a mobile application.

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.

Authenticating users in iPhone app

I'm developing an HTTP api for our web application. Initially, the primary consumer of the API will be an iPhone app we're developing, but I'm designing this with future uses in mind (such as mobile apps for other platforms). I'm trying to decide on the best way to authenticate users so they can access their accounts from the iPhone. I've got a design that I think works well, but I'm no security expert, so I figured it would be good to ask for feedback here.
The design of the user authentication has 3 primary goals:
Good user experience: We want to allow users to enter their credentials once, and remain logged in indefinitely, until they explicitly log out. I would have considered OAuth if not for the fact that the experience from an iPhone app is pretty awful, from what I've heard (i.e. it launches the login form in Safari, then tells the user to return to the app when authentication succeeds).
No need to store the user creds with the app: I always hate the idea of having the user's password stored in either plain text or symmetrically encrypted anywhere, so I don't want the app to have to store the password to pass it to the API for future API requests.
Security: We definitely don't need the intense security of a banking app, but I'd obviously like this to be secure.
Overall, the API is REST-inspired (i.e. treating URLs as resources, and using the HTTP methods and status codes semantically). Each request to the API must include two custom HTTP headers: an API Key (unique to each client app) and a unique device ID. The API requires all requests to be made using HTTPS, so that the headers and body are encrypted.
Current strategy:
My plan is to have an api_sessions table in my database. It has a unique constraint on the API key and unique device ID (so that a device may only be logged into a single user account through a given app) as well as a foreign key to the users table.
The API will have a login endpoint, which receives the username/password and, if they match an account, logs the user in, creating an api_sessions record for the given API key and device id. Future API requests will look up the api_session using the API key and device id, and, if a record is found, treat the request as being logged in under the user account referenced by the api_session record.
There will also be a logout API endpoint, which deletes the record from the api_sessions table.
Does anyone see any obvious security holes in this?
I agree with the oAuth comments - you can of course make oAuth work nicely on an iPhone - the UX is totally up to you. There are mechanisms (jQuery) to pull back the PIN from oAuth and use it (without the user re-typing the PIN into the app). That reduces the UX to
1) Display web page (in embedded control)
2) user enters user and password and presses button
3) oAuth response page is parsed automatically.
This twitter oAuth implmentation does that http://github.com/bengottlieb/Twitter-OAuth-iPhone using a pre-existing oAuth library.
However, back to your original question. That looks fine. The only item you don't mention, is that you need to provide a mechanism on the web app to allow the user to logout/deauthorize a device session (in case they have lost their device).