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

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

Related

How To Access Google Calendar Access Token using Username and Password from Node server

I am trying a post-call to generate an access token using the client username and password. I would like to know how we can achieve this through Node Js Code.
Generally speaking, access_token are rattached to the OAuth2 authentication framework, which doesn't require the application owner (you) to have access to one of your user email/password. This is a more secure approach that is broadly adopted.
The way OAuth2 works on the Google Calendar API is a 3-parties (or 3-legged) authorization. Let's take the example of a user that browses your website and want to sign-in using its Google Account. The steps to authenticate him are the following:
The user clicks on "Sign-in with Google"
The application owner (you) performs a request to Google saying that a user wants to connect (that's the OAuth consent screen)
Google replies by giving you a URL (authorizationUrl) where to redirect the user
On that URL, the user is prompted with several information about your application and can grant access.
When the user has granted access, Google will redirect the user to your application success page (callbackUrl) with a unique code.
Using that code, the application can retrieve an access_token, which temporarly lets your application performs requests on behalf of a user.
These steps are a rapid overview of the OAuth-flow, also known as the OAuth dance. To make POST requests to the Google Calendar API, you will have to perform that OAuth dance for every single of your users.
Implementing that flow can be tricky. Fortunately, Google gives very helpful documentation on that. If you don't want to bother, you can also use API-tools (like Pizzly) that takes care of that for you.

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

Ionic and Firebase Authentication Security with Domain Restrictions

I'm using Ionic with Firebase Authentication (Google sign-in method) to authenticate users. I've got the authentication working. The problem is I want to only allow access to my application (login --- rather than authentication) if the user is from my company's domain (jimmy #neutron.ca).
I only want my employees logging into the app and gaining access to the interface beyond the login page. I only want my employees to be able to submit their hours (that's the scope of the application after login).
My question is, what is a secure way of authenticating a user and logging them in?
Is it secure to calculate on the client-side ionic app wether or not the user is of a particular domain after we get the authentication object back from firebase google sign-in method?
login() {
this.afAuth.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider())
.then(res => {
// example email object = 'jimmy#neutron.com'
// get email object, split('#')[1] on it
// if result of split (#neutron.com) is eqaul to my domain (neutron.com), which it is, then log user in
this.navCtrl.setRoot(AuthenticatedPage);
// if not, unauthenticate and present unauthorized message to user.
})
}
If this isn't secure to do in ionic on client-side, then how can we calculate it? Can firebase calculate it?
If I understand this correctly. You need to pass hd custom OAuth parameter to Google provider:
const provider = new firebase.auth.GoogleAuthProvider();
provider.setCustomParameters({hd: 'neutron.ca'});
this.afAuth.auth.signInWithPopup(provider);
However, users could still bypass that as Google doesn't enforce it (check the email domain).
You need to also enforce that via your security rules (if you are using Firebase Rules) or when you parse the ID token and verify it via Firebase Admin SDK.

How to add user authentication to botframework app?

Trying to build a recipe ordering app via SMS using Bot Framework. How can I let the user 'login' to view all his previous recipes?
The user first must sign up through a website using Azure Active Directory B2C. I got the API sample template up and running and it lets me authenticate user through the website...
But I'm not sure how to authenticate this logged in user (on the website) on the bot chat level. How can I make Bot Framework be aware of this logged in user?
It'd be really nice if you could just turn on multi-factor authentication and access the phone number connected to the user but this is not possible programmatically at the moment according to Microsoft.
Any other ideas? I desperately need some way to allow a mobile phone user to authenticate via SMS and access their private data through it. I tried it with Active Directory's .net api sample but no documentation exists on how to make this all work together with Bot Framework...
I ran the pizza bot template and pondered upon the same question.
I ended up taking the user ID and store it along with any information I could get through claims. Then, I a reference for the user that I can look up and do stuff with. Not sure if this helps you.
This is how you can do it:
Generate an authentication URL and send it to your user via the bot. Ask him to login to the service using the URL.
The server would receive the result of that authentication (your API for the bot is now aware of the result) and if successful, you can show the data to the user through the bot.
You might want to take a look to the Facebook Auth sample to get an idea of a potential flow for the Auth scenario.
Hope this helps.

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.

Resources