Verifying a Facebook Connect session - facebook

I am writing an application which has multiple frontend clients using Facebook Connect as a single signon solution.
One of these clients, for example is running on the iOS platform, so all fb authentication happens on the client via the iOS Facebook SDK. After a user authenticates on the client, however, since I am using Facebook for signing in to our site, is there anyway for the server to take the auth data from the client, and verify it?

Using the Javascript SDK, call FB.getSession() to get a JS object with various auth-related bits. Of these, pass 'access_token', 'expires', 'secret', 'session_key', 'uid' and 'sig' along to your server.
On server-side to check if the call is authentic, concat these into a string such as "access_token=1290380d9e&expires=92d903&secret=e9cj9kd&session_key=s49i9i3f&uid=12345". So everything you just passed, EXCLUDING the sig.
To this string, concat the "app secret" which you can get from Facebook developer site. Take the MD5 hexdigest (in Python import md5;md5.new(foobar).hexdigest()) of the string and compare to see if it is the same as the 'sig' you passed.

Related

Facebook OAuth security using passport-facebook

I am currently using a client-side React component to have a user login to Facebook via OAuth in my application. On the server-side, I use the npm package passport-facebook-token to validate the authenticity of the accessToken after a successful client-side login.
One practice I do not see often is in addition to asking Facebook if the accessToken is valid, shouldn't the server also check if the email provided by the client's payload matches the e-mail coming back from Facebook? Allow me to use defined client/server technologies to illustrate my question:
1) User uses React component on the client to authenticate with Facebook.
2) React component successfully authenticates with Facebook and fires an HTTP request to the server with an access token and the user's email.
3) The server, running Node.JS and passport-facebook, now needs to verify the authenticity of the access token directly from Facebook. Facebook does not care for an e-mail. It will just verify the access token.
4) Facebook returns a response to Node.js confirming the authenticity of the access token. The response also contains other metadata about the user, including their email and other profile data.
My question is, should Node.js take the email that's also coming back from Facebook's access token verification payload, and verify that it is what came back from the React client? Would this not prevent someone from brute-forcing an accessToken and require them to not only have an accessToken but also know who the accessToken belongs to? This could prevent a user from submitting a bunch of HTTP POST requests to the Node.js server attempting different access tokens. They would not only have to guess an access token assigned to the application's clientID, but also know the e-mail it belongs to. Is this an over-engineered approach?
Really the best way I can think of to make your OAuth accessToken and 'code' value less prone to brute-forcing is using a Cryptographic Number Generator to create a 128-bit length string of random data and encoding it with base 64 to use as your code. It's extremely unlikely that it would be guessed by a computer or by someone redirecting to and from the authorization endpoint and the redirect-uri with query parameters.
Another method of fortification is limiting the rate of authorizations by IP address (which you can do instead of email through Node.js) but that is usually not a problem for most well-equipped hackers. I highly advise the first method for creating a more secure service.
Your approach to validate the email as well as the token is a bit superfluous because Facebook's opaque user access tokens are inherently tied to email.
From Facebook
An access token is an opaque string that identifies a user, app, or Page
"opaque" is defined by Auth0 here
Opaque Access Tokens are tokens in a proprietary format that typically contain some identifier to information in a server’s persistent storage
In your case, the identifier is the user's email, and the server belongs to Facebook.
I will elaborate further. Here is your step by step with some edits:
User uses React component on the client to authenticate with Facebook, inputting both their email and password directly to Facebook. React component gets the token from Facebook on login success.
React component successfully authenticates with Facebook and fires an HTTP request to the server with an access token and the user's email.
The server, running Node.JS and passport-facebook, now needs to verify the authenticity of the access token directly from Facebook. Facebook does not care for an e-mail. It will just verify the access token because the access token is already tied to the email.
Facebook returns a response to Node.js confirming the authenticity of the access token. The response also contains other metadata about the user, including their email and other profile data.
This is Facebook's bug bounty program. If their OAuth was really as cracked as to require a second email validation, it would have been patched almost immediately by this incentive.

How to connect & authorise google auth iOS client with Kitura Server?

I'm done setting up the server by following steps given here.
OAuth does work with google but only for web-client
On iOS client, I've followed steps to integrate google sign-in by following steps given here
Let's say there is a get route localhost:8080/api/v1/movies should be accessed by users who are logged in, how do I achieve that?
User has already logged in, on iOS client.
How do I pass iOS client's google authorisation information to server?
I believe that once your client has completed sign-in, you will have a GIDGoogleUser that provides access to an ID token (JWT) that you can supply to your server. Your server can then validate the token (that it was issued by Google) and extract the user's identity.
See: https://developers.google.com/identity/sign-in/ios/backend-auth
You may be able to use the Kitura-CredentialsJWT middleware to decode the token. Note that as of writing, the plugin only supports Codable routes, but there is an open pull request that adds support for 'raw' routing (using the Kitura-Credentials plugin mechanism).
Update: Kitura-CredentialsJWT support has now been released in tag 1.0.0.

Facebook login architecture

I'm developing an App which uses Facebook to authenticate. So far, what I have is the following:
Client->FB: authentication data (fb user & password),
FB->Client: FB id, FB token,...
Client->AppServer: FB data (id, token,..)
AppServer->Client: OK/Not OK, whatever necessary data.
Where:
Client: The App installed in the user's device (in this case, iOS),
FB: FB server (the client talks to it through FB's SDK),
AppServer: My App's server.
The point of all these is to validate if the user is real. The problem is that in #3 the Client could be sending a random FB id or FB token to the AppServer, so the question is: is there anyway to check in the AppServer whether this FB data is indeed real?
This worked for me:
Given a FB_CLIENT_TOKEN and FB_CLIENT_ID coming from a client, and knowing your FB_APP_ID and FB_APP_SECRET, we want to validate in our server if the fb account from the client is real. Then:
From server, access https://graph.facebook.com/oauth/access_token?client_id=FB_APP_ID&client_secret=FB_APP_SECRET&grant_type=client_credentials
This will return a plaintext with access_token=APP_TOKEN.
Next, access https://graph.facebook.com/debug_token?input_token=FB_CLIENT_TOKEN&access_token=APP_TOKEN
This will return a JSON with a field named user_id, so the last step is to check if this field equals FB_CLIENT_ID.

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.

Restfull web application with oauth when client is also a website

I am creating a solution that will contains a website and mobile apps. I will use Zend-Framework 2 for the website.
So, to make it good, I am wondering if it would be a good idea to build :
A REST web service (using zf2)
Another website that will call the REST ws (using zf2)
The mobile apps that will call the REST ws
I will use OAuth for the autentication and security.
My question is, if my website gets the data by calling the REST ws, it will have to make a database request at each call to check the token whereas if I do a "normal" website, my app will be able to use session to store the information of the connected user.
Because, for what I have read, there is no such thing as session with OAuth/REST so for each call, I have one more sql request to check the token validity.
Is it still a good idea to make a full REST service, even for the website or to have a "normal" website and also a REST service API just for the mobile apps ?
Thanks
Oauth is a server to server authentication framework. Like it is between mobile app and your API server , website vs your API server etc. You can adopt an approach where , you generate only one access token for your website client instead of multiple access token for each user from the website. This access token is stored in your webserver vs user cookie in website.Ultimately the aim is to identify all the clients of your REST WS and your website is one of its client and a very trusted one.
This way you can cache the access token to avoid db calls (typically cache time can be equal to or less than token expiry time). Do explore the multiple grant types specified in the oauth spec for this
Regarding maintaining session for user in your website, it is not dependent on whether the back end is a REST WS or not, it can be handled in your website