Testing authentication on nodejs app with facebook test users - node.js

I'm testing the Facebook authentication on my nodejs webapp and I'm banging my head against the customization of the content of the test-user's token.
I'm first creating a Facebook test-user with my facebook_app_id.
It gives me an id, an email, a token... And I'm using that last one to create a user on my webapp. This works without problem. There's an 'email' key in that one!
The real test starts here. I'm now trying to log using my Facebook test-user access token. The test fails because there's actually no key 'email' in the access token (which I'm using internally to identify the user).
I've been searching throw the GraphApi documentation to see if there was any way to get that information in the token (like permissions?) in vain.
Any idea? Am I doing something wrong here?

Related

Getting Google User ID in Node.js in Firebase Functions for Assistant App

I'm getting started with Google Cloud Platform.
I'm developing an Android App that will collect information and store it in a Firebase App. The idea is that a Google Assistant function can query this information and read it back- eg
OK Google, Talk To Simons App, Tell me the last time XYZ was done
The problem I've got however, is to get this being multi user.
I've got the Android App collecting data and putting it into the cloud. I'm using the FirebaseUser and using getUid() in the Android app to get a unique id which is a 28 character string like uVHkia8RRgWD8GGPVvW4AUDUK2.
I've setup Actions on Google, got it hooked into API.AI with Web Fulfilment and got Node.js working in firebase functions.
Unfortunately, the UserID I get back looks more like:HTge48H0CF2FC5jJQCigFBc-UCQ
The problem is that this UserID is not the same as the UserUID I got from Filebase User.
Im using
let ApiAiApp = require('actions-on-google').ApiAiApp;
const app = new ApiAiApp({request: request, response: response});
and
const userId = app.getUser().userId;
What am I missing? I see references to OAuth2, Account Linking etc. I'm not entirely sure what to do at this point. All I need to do at the moment, is get the User UID like I get from FirebaseUser.getUID() in order to look the data up in the Firebase Database.
I think the rest should be straight forward.
There's loads of documentation on linking to Firebase from the Assistant, but very little on actually authenticating. So far I've not setup an flows, like Authorization Code Flows, Implicit Flows, or set a username/password against API.AI and the Fulfilment option. Quite frankly Im not sure what needs to go where at this point.
The user provided by app.getUser().userId is designed as a persistent anonymous identifier. It is roughly the equivalent of a cookie that one sets in a web server - you can use it to determine if you've seen this user before, and what else they've done in your Action, but it does not inheriently relate to any outside account.
Unfortunately, the best solution you have at this point is to use Account Linking which requires you to setup an OAuth2 server. As part of this setup, you will need to create three components:
A login web page for your service. You'll provide the URL for this page to Google as part of Account Linking. When the user accesses your Action, and your action indicates they need to log in, they'll be redirected to this URL on their mobile device. On this page the user will log in - once logged in, you now know their Firebase ID and will create an auth code for this user. You'll then redirect them back to a different URL and pass this auth code (along with some other info) as a parameter.
A token exchange endpoint. Google will call this URL with the auth code above. You'll verify this code, determine who the user is, and send back a unique access token. (You'll also send back a refresh token that Google will use in the same way to get an updated access token.)
An auth token handler in your webhook. When API.AI calls your webhook, it will include the access token as one of the fields in the request. You can use this access token to get the Firebase ID for the user.
One thing to note for the auth code, the access token, and the refresh token is that you'll need to have some way to map from these codes/tokens to the Firebase ID. There are two good ways to do this:
The code/token can be a JSON Web Token (JWT). This takes the Firebase ID, and other information you wish to retain about the user, and puts it in a standard format. It then creates a cryptographic signature, to make sure it hasn't been tampered with, and encodes it in a standard format. When you need to determine the ID from the JWT, you can decode it, verify the signature is valid, and read the value.
Generate a random string and store this in your database against the Firebase ID. When you get the token, you can then look up in your database the ID that this string was assigned to.
There are many additional details about an OAuth implementation and about each of these steps. See https://developers.google.com/actions/identity/oauth2-code-flow for more details.

how to get Azure Active Directory B2C working with Bot Framework?

so far I've not been able to get this working with the bot framework. I spent all day but only managed to get .net api example (https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) working with AD B2C. I'm not sure where it grabs the bearer token that I want to pass to BotUserData...
I've tried following https://azure.microsoft.com/en-us/blog/bot-framework-made-better-with-azure/
but in reality the solution does not build successfully and I've resorted to just taking code from there and into my bot framework sample template....however, when it asks me to login through MS and I do, I am not able to proceed and it doesn't seem like that blog is using the AD B2C policies.
so how do you integrate AD B2C with Bot Framework? Is it possible to call /Account/SignIn URL from bot framework to authenticate the user? Afterwards, how would you capture the token and pass it to BotUserData?
You might want to take a look to the Facebook Auth sample to get an idea of a potential flow for the Auth scenario. For Azure AD, you need to do a similar flow.
Let's say your user send a "Login" message to your bot. The bot should respond with an auth URL and ask the user to login to the service using that URL. You can use the GetAuthorizationRequestURL method of ADAL for that.
Then you will have a Web API which will basically expose an endpoint that will be the reply URL of Azure AD. Once the users completes the login, a message will be posted to your Web API where you will be able to get the authorization code and perform the calls to get the Access Token. After that, you can just do the same they are doing in the Facebook Sample Web API which involves resuming the conversation with the Bot, sending a message with the access token (so it can be persisted in the PerUserInConversationData bag (check this line of code).
After that you have the access token available to perform any call that requires an access token.
Update
There are two new samples that you might want to take a look since they are implementing the workflow being discussed.
GraphBot from the BotBuilder repo.
AuthBot from Mat Velloso
Hope this helps.
Follow this tutorial for Bot side code development, i focus on configuration at B2C and Azure level here:
OAuth Connection
Client id
This is taken from the Application ID field in your B2C app's properties. It's the equivalent of a Microsoft app ID taken from any other AAD app registration.
Client secret
This is generated using the steps in this tutorial.
Select Keys and then click Generate key.
Select Save to view the key. Make note of the App key value. You use the value as the application secret in your application's code.
Use AAD V2 configuration in oAuth settings in bot channel registration - new oauth connection settings.
Fill the above details by following the steps and values we got from them.
Authorization/Token/Refresh URL
I followed on this one with
https://login.microsoftonline.com/tfp///oauth2/v2.0/authorize
for the Authorization URL and
https://login.microsoftonline.com/tfp///oauth2/v2.0/token
for the Token and Refresh URL's.
For I used the URL format (kyleorg.onmicrosoft.com) rather than the GUID format, but using the GUID also seems to work.
is the name of a user flow, like B2C_1_userflow. I created one with this tutorial.
Scopes
Using the scopes openid offline_access I am able to sign in successfully, but to my astonishment the token returned is empty.
Then I found this document which suggests using the client ID itself as a scope.
When I reuse the value from the Client id field in my Scopes field, a token is returned successfully and my bot is able to use the connection.
You can combine this with other scopes as needed, but for the sake of experimentation I highly recommend getting the simplest implementation to work first.
Let me know if these instructions work, and if they don't then we'll see if the difference lies in how we've set up our B2C apps.
As a bonus, I should mention that after you get a token you can paste it into https://jwt.ms/ to decode it and see if it recognized your B2C user correctly. Always refresh the page when pasting a new token to make sure it doesn't keep showing you the information from the last token.
Referred this document.

How to do authentication for an API build with express?

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)

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