How to do authentication for an API build with express? - node.js

There are quite a few examples and tutorials on authentication and node out there, as well as several questions on stackoverflow. I'm still struggeling with this subject however when trying to implement authentication for an API which communicates with a SPA. I tried using mean.js as an example as well as to use JWT and passport.js. But even after some days of research and trial and error it is still unclear to me how to achieve the following scenario:
A user registers himself with a username (or email) and a password (and gets an email to verify his account)
The user logs himself in with the password and username.
The user recieves a token as a response
The token is used in all following requests which require authentication (and is invalidated after a given amount of time).
If the user logs out, the token is invalidated and he gets a new one the next time he logs in.
At a later point of time I also would like to implement Facebook and Google Login (that's why I would like to use passport.js).
I'm glad for any help and also open to suggestions for a better authentication flow.

Looking into Firebase (https://www.firebase.com/). It simplifies the process of handling Auth and all the perils of trying to handle Auth yourself.
Firebase also supports all of the major Auth providers out of the box (Facebook, Google, Twitter, etc).

I ended up using the node-example of satellizer:
https://github.com/sahat/satellizer/blob/master/examples/server/node/server.js#L36
You store password and username to the database on signup.
For logging in one can you simply compare the (hashed) password with the proved one and send back a token you create via jwt.encode (jsonwebtoken).
After that you append the token to your requests (in the header is probably the best way) and check its validity via jwt.decode(token, TOKEN_SECRET)

Related

Can anyone outside use my api to make requests?

I am currently learning full stack dev, and have made a simple application with React on the front end, and set up a very simple REST api on my express web server that handles certain routes.
For example api/users returns a list of users from my database and returns responses as JSON data. api/blogs can return a list of blogs in JSON with a get request, or post a blog with a post request.
I have learned and been able to implement very basic user tokenization with JWT, and so only logged in users with a valid token can make a post of a blog for example. This is done by adding their token with bearer as a Authentication header in the request, which the server verifies. This makes sense to me, however I am very confused on how the backend works or if I am doing something critically wrong.
If I go to my main page for my application, and type api/blogs it opens up a page displaying JSON data. Anyone can basically view this from my application by going to api/endpoint
I am also assuming anyone from outside can use something like Postman to send a post request to my database assuming they have the token which they got since my token is saved in storage.
This is incredibly weird to me Is this just how these things work? Or am I failing to understand something crucial?
if I wanted to progress forward and learn more about this, where or what do I do?
You have described how users authenticate to your application (with a bearer token), but what steps does your application take before issuing such a token?
Does your application keep a database of users and their passwords?
If yes, can anyone sign up by inventing a user name and password?
Do you verify an email address before admitting a new user?
Or does your application rely on an external OpenID Connect service (for example, login with your Google or Facebook account)?
If yes, can anyone with a Google or Facebook account sign up for your application?
Or must an application admin (that is, you) put the user on an "allow-list"?
To summarize: Unless you take special precautions, anyone from outside can sign up to your application and subsequently use it.

How can I verify login using google api, oauth?

I want to use google oauth api to log in to the site which I create.
I use react and node and I'm done with getting current access_token issued but I'm not sure how to know if the user is logged in.
Should I check the user's access_token every time the user calls the api of my site?
If that's correct, should the access_token be held by the client?
Isn't that a security issue?
I did a lot of searching but I don't know how to manage access_token and how to check if user is logged in.
This is the article I referenced
Should I check the user's access_token every time the user calls the
api of my site?
Yes. The only ones you will not check will the public ones.
If that's correct, should the access_token be held by the client?
Yes, it can be stored in cookies, local storage... Is is debatable which is the best solutions, you can articles such as this one
Isn't that a security issue?
No. Anybody can check the content of a JWT token (just paste the content here). But the neat thing is that it can't be modified or manipulated. Of course, it is advisable to keep it as safe as a password, so don't share it around :)

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

Facebook login flow with to nodejs

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.

using facebook client flow to authnticate and login on app/site

Other then the fact that when using facebook's client-flow you get an access token right away, and when using the server-flow you first get an authorization code that you have to exchange for an access token, What is the difference between the two flows and when should I use each of them ?
more specifically can I use client-flow and still be able to securely log a user into my application/site?
At first glance I though that I could take the access_token and id I got on the client (via client-flow), send them to my server and then if a graph api call for that ID and token does not break I can assume I am dealing with this user and log him into my site based on his FB ID.
On second thought it looks to me that If I don't follow the server-flow there is no way to securely use the client id & access_token to log the user into my application/site.
The reason I say this is that another (hacker) app owner that "shares" a user with my app. might take the access_token and and ID he (illegitimately) got for user on his authorization flow, and fake a call to my site with this data causing me to log him in as if he was this user.
Am I missing something here?
Should this not be written in big red letters on the first paragraph of https://developers.facebook.com/docs/authentication/ ?
Oauth 2 (http://oauth.net/2/) is what Facebook uses. For the most part it is the most secure interface available. If there was a way for a user to take an access token for one app and then use it in another app, then oauth2 will need to be patched (or Facebook oauth2 will need to be patched).
If you think you found a way to hack it, then you should get your $500.00 prize from http://www.facebook.com/whitehat/bounty

Resources