Facebook login flow with to nodejs - node.js

I am working on a REST API backend service for an app that uses both email and facebook login. Lets just pretend this app is a todo list app and a user can sign in and add notes which they could later view on may different devices.
The "Login with email" is pretty simple, the app would make a request to:
URL: /v1/login
Params: email, password
Then the serivce returns an access token if all this information is correct so we know the identity of the user creating, updating or deleting a note/list item.
Now for the facebook side. I've seen several differnet answers all over StackOverflow and Facebook's documentation. Some people say, just pass in the id and login the user with the matching id. This would mean calling the login function from the Facebook SDK and just keeping that id to send in a request.
URL: /v1/login/facebook
Params: id
That would work but seems highly unsecure. Anyone could get someone else's Facebook id and just send a request to the server. Facebook's documentation mentions also using the account email. We'll what if the user ever changes their email on Facebook, they could never login to this app again. Another hint of security would be passing in the token from Facebook every time. Since those tokens can change or expire, there really wouldn't be a way login past the expiration date.
The final method I know of would be passing in the app secret:
URL: /v1/login/facebook
Params: id, secret
This seems by far the most secure, if you are using https to connect to the server. The downside to this method is, what if the Facebook secret token is ever reset? I mean you could always make a call to the server to request and check if token was reset and if so pass back the new one. But then if anyone had access to the endpoint to check out of date tokens, it could give them the new secret token.
I know we are dealing with the internet here and there will always be security flaws and there isn't a perfect way to do this. But what is the best way?

Try to send facebook_token for that user.
URL: /v1/login/facebook
Params: facebook_token
and service side make a service call to facebook graph api to get information about that user using facebook_token.
get the facebook id from that response and use it to provide data to that user.

Related

Handling Social Media Integrations in a MEAN stack App after a user is Logged in

A user can create an account in my App only with his work email.
Example: john#xyzcompany.com
After he creates an account, he can link multiple social media accounts to his profile.
Example: john#gmail.com, john2#gmail.com
I'm using MEAN stack to develop the App.
When a user logs in to my app, I'm creating a JWT token to authorize all his future requests to the server.
When it comes to Social Media accounts Integrations, After successful authentication I'm able to receive the accessTokens from these Social Media to the backend callback URL. I need to link the tokens to the right user. Is there anyway I can pass my JWT token along with the callback URL to identify which user has made the request, because I cannot identify the user based on the email in his Social Media Account?
I was able to solve this using socket.io. But I feel it is unnecessary to use sockets for simple authentication.
Is there any other approach to solve it? I have researched online, few of them suggested using passport. I don't fully understand how passport works, I just feel it is just a middleware to authenticate API requests from users, which I'm doing anyway using a custom function.
Could someone explain whether it is possible to pass JWT in callback URLs using passport strategies?
What is the right approach to handle such authentications in a MEAN stack app? I'm stuck with this issue since the past week, really looking forward for a good solution.
I have encountered this type of situation in one of the large scale applications I have been working for and the approach we used to handle it was to store the jwtToken in redis and then retrieve it back with the help of user cookies. Let me explain it in more detail -
Send a new Cookie for the user when the user opens the login page. The cookie should contain some unique id or code against which we will save the JWT token,. Eg: res.cookie('jwtIdentifier', newid())
Now, when the user logs in, generate the JWT token and save it to your redis against the cookie jwtIdentifier's value. Eg: redisHelper.set(req.cookies.jwtIdentifier, JWTTOKEN)
At last, when the login is successful and the user is redirected back to your app, you can retrieve your JWT token again for the corresponding user using the cookie. Eg: redisHelper.get(req.cookies.jwtIdentifier) This will give you back the JWT token that you can then use across your application for that specific user.
Hope it's clear, let me know if you have any questions with this implementation ;)
You might try using client side facebook authentication as described here
https://theinfogrid.com/tech/developers/angular/facebook-login-angular-rest-api/
in this case in angular app you have facebook token alongside your app token and you can send them to your backend to identify the current user.
on backend part you eill call facebook to get profile data from accessToken and then store user profile id and depending on your business you might need also to store the access token

How to get online status of facebook user?

I wanna to understand how I can retrieve the online status of a Facebook user. For example, I'm logged in my application through JWT auth, and then in my settings page, I wanna to see my facebook online status.
Do I need to log in through OAuth, or just I can put on the field my facebook userID and then make a request to facebook API?
Also if it's possible to have socket connection with that online status to know in real time my status?
Maybe do you know cases with node.js and socket.io with it?
Thx
There is no way to get a user’s “online status”.
Do I need to log in through OAuth, or just I can put on the field my facebook userID and then make a request to facebook API?
Even if you did make an API request with a valid user token, that says little about the user’s online status.
The token stays valid for two hours (for a short-lived one), but the user isn’t necessarily online “on Facebook” for the whole time. Only if they logged out of your app explicitly, thereby invalidating the token, you could take the error message you would then get on the next attempt to make an API request using that expired token as an indicator. But then they would also have to login to your app again, before you could recognize them as “online” again.

Clarify some things about OAuth2.0 and Node.JS REST API

I'm currently developping a REST API with NodeJS and Express for a mobile application written with the Ionic framework.
I have a mysql database in which are stored my users.
I want my API to be safe concerning the authentication of my users and their right to access certain routes and ressources of the API.
My user can either login/register with their own credentials or use Facebook to do it.
So, this is what i'm doing right now :
A user register using one of my API's routes
When he wants to access a protected route, i use passport-http's Basic Strategy for Basic Auth.
I use it like this:
router.route('/protected/route')
.put(auth.isAuthenticated, controller.someMethod);
The auth.isAuthenticated looks like this :
passport.use(new BasicStrategy(
function(username, password, callback) {
Account.findByEmailAndPassword(username, password, function(err, user) {
if (err) { callback(err) };
if (!user) { return callback(null, false); }
return callback(null, user);
});
}
));
exports.isAuthenticated = passport.authenticate('basic', { session : false });
Then, in controller.someMethod(), i get my user object in req.user. I have a field in my DB that is type, i can check what's the type of the user and continue my request or not.
Now, using Facebook:
The client uses Facebook's Login button, authorize my app to access it's data, and then gets an access_token. It is send to my API via an HTTP request.
The API gets the token, and then start calling the Facebook Graph API to ask information about the user such as his id, email, firstName and lastName.
I send theses informations back to the client. He's able to modify his firstName and lastName if he wants. Then send it back to the API.
The API register the User.
They both works like a charm, but i'm facing some problems:
When registering with facebook, if the user id is already in the database, i consider that the user has already subscribed to my service. But how can i identify him using basic auth afterwards ?
The first question brought me to the others. I've read everywhere that Basic Auth isn't secure enough. So i was thinking about, first of all, buy a SSL certificate, then change my authentification system to OAuth 2.0.
I was thinking that if i do that, i would be able to send a token back to my user that logged in with Facebook, which would answer my first question.
But is OAuth2.0 the solution here ?
Am i doing things right with my Facebook registration ?
How does that callback stuff works when i want to login using my own users on my Ionic app ?
There's so many things that seems unclear about OAuth2.0 that i don't want to start implementing it and then figure out than it wasn't the right solution for my problem. I've always thought that OAuth2.0 was the right system to choose if you want other services to use your service. I am wrong?
Okay. So first thing first. HTTP Basic is perfectly secure if you are doing it over SSL.
OAuth 2.0 is an authorisation method.
OAuth is used when you want to make API calls on behalf of a user registered on other service. The other service has to provide the OAuth functionality for it to be usable by you. Let's say, you don't want to have a Registration function in your app but want to register users via Facebook, etc, you'll give an option to sign in using Facebook. So what happens is you are asking the user to give you access to access some of their Facebook account's info (more or less). You can read about it here: https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2
On the other hand, you can be the provider so that other services can use your service.
Many services let you create a local account and also give you an option to signup with other services like Facebook, Google etc..... The handle the cases on their backend side.
Let's say you want to give option of Sign in with Facebook, you'll have to take care of a couple of cases:
Associating Facebook Login with an already logged-in account - This is the case where someone uses an app's custom login system to create an account. Later, while they are still logged in they want to associate their Facebook account with it. For example, people can sign up to Spotify with an email address and a password, but they can later choose to associate that account with their Facebook account using Facebook Login, such as when they want to publish their listening activity to their timeline.
For this, you want to add a Facebook log in flow, like Spotify does.
One thing you have to take care is the merging of your local account and the Facebook flow account info. It is advised that you create separate tables for this as this will ease the process when you want to add more providers like Google, etc.
Merging separately created accounts with Facebook Login - In this situation, a person logged in to your app with their own credentials such as an email and password for example. Later, when the person logs out they choose to sign in to your app using Facebook Login. Your app will now have two accounts for the same person, one created via the app login system, the other created via the Facebook Login flow. In order to provide the best experience for that person, your app should attempt to merge these accounts into one.
For this you have to request for email (assuming your app requires email for registration) from Facebook. If it's the same as the email registered in your app, you can merge these accounts. If it's not the same, then you should give an option to connect existing email/account.
You should go through the following for more info: https://developers.facebook.com/docs/facebook-login/multiple-providers

how to secure azure mobile service / html - javascript

When I call an oauth provider like gmail and I get the token back, how can I make sure that all future calls I make are from that same client that did the authentication? that is, is there some kind of security token I should pass pack? Do I pass that token back everytime?
For example, if I have a simple data table used for a guest book with first,last,birthdate,id. How can I make sure that the user who "owns" that record is the only one who can update it. Also, how can I make sure that the only person who can see their own birthday is the person who auth'd in.
sorry for the confusing question, I'm having trouble understanding how azure mobile services (form an html client) is going to be secure in any way.
I recently tried to figure this out as well, and here's how I understand it (with maybe a little too much detail), using the canonical ToDoList application with server authentication enabled for Google:
When you outsource authentication to Google in this case, you're doing a standard OAuth 2.0 authorization code grant flow. You register your app with Google, get a client ID and secret, which you then register with AMS for your app. Fast forwarding to when you click "log in" on your HTML ToDoList app: AMS requests an authorization code on your app's behalf by providing info about it (client ID and secret), which ultimately results in a account chooser/login screen for Google. After you select the account and log in successfully, Google redirects to your AMS app's URL with the authorization code appended as a query string parameter. AMS then redeems this authorization code for an access token from Google on your application's behalf, creates a new user object (shown below), and returns this to your app:
"userId":"Google:11223344556677889900"
"authenticationToken":"eyJhbGciOiJb ... GjNzw"
These properties are returned after the Login function is called, wrapped in a User object. The authenticationToken can be used to make authenticated calls to AMS by appending it in the X-ZUMO-AUTH header of the request, at least until it expires.
In terms of security, all of the above happens under HTTPS, the token applies only to the currently signed-in user, and the token expires at a predetermined time (I don't know how long).
Addressing your theoretical example, if your table's permissions has been configured to only allow authenticated users, you can further lock things down by writing logic to store and check the userId property when displaying a birthday. See the reference docs for the User object for more info.

Authentication using Facebook with Passportjs: what is accessToken for, what should I store after registration?

I am using Passport to register/authenticate using Facebook.
When oAuth is successful, I am returned:
accessToken
refreshToken
profile
Now... when a user successfully registers using Facebook, I store accessToken and the profile info.
When somebody wants to login, and goes through the oauth motions again, my app once more gets accessToken and profile.
Trouble is, accessToken is different. I actually expected the accessToken to be the same after the first authentication...
At this point, I am connecting my own local user with the facebook's id field from the profile. But... how would I actually use accessToken? Does it even make sense to keep it? If so, why would I actually keep it?
I actually expect accessToken to be the same, and use that to match a successful login. I obviously can't do that... so I am confused!
You need to keep accessToken if you want to query facebook's API on behalf of your logged-in-via-facebook user. If you want to use facebook just for login only, you can discard it. If you want to ask facebook for the user's most recent status update, for example, you need to include that accessToken as a parameter when making that API call. The point of the accessToken is that it allows a set of operations on behalf of a user, but it expires so if it falls into the wrong hands it cannot be used to cause as much damage as a permanent token or the user's actual password. It will be different every time by design.
You should store facebook Id. It should be in the profile object. Access token will change according to facebooks policy of authorization. What you should be doing is
Get the user to login through facebook
Check their facebook id against the facebook id in your database.
Access tokens expire frequently as described here

Resources