Facebook OAuth security using passport-facebook
Asked Answered
H

2

3

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?

Hawser answered 16/5, 2020 at 22:14 Comment(6)
#1 Would this not prevent or Would this prevent ? #2 Your last paragraph is a little confusing to me. Is your question related to add an extra validation (email from react and email from facebook must match) to the current authorization flow provides and proposed by passport nodejs?Scorekeeper
I edited my question. I hope this adds more clarity to what I am trying to ask.Hawser
Why would you want to do step 3 and 4? Facebook is providing oauth based login. Facebook has done the validation for that particular user. Now the access token can be used to access facebook APIs. I don’t feel you need to verify the access token. Can you describe the use case/scenario better so that I can understand what you intend to achieve?Hakon
@Hakon Facebook has validated the user on the client. The server needs to trust that this validation was authentic.Hawser
#1 Are you sure that react is able to get the email before the access_token is sent to the backend(nodejs)? #2 is a proof of concept or is an enterprise application? #3 Will you have more web with facebook login or just one?Scorekeeper
Your OAuth flow looks a bit strange to me. In general lines what happens is: React client calls your backend to log in, Your backend triggers facebook auth that redirects to the Facebook's login page where the user logs in and give his consent. After that Facebook calls your URL callback and sends you the data of the user. You get this data, generate an auth token(a JWT token for example), and send it to the react application use it in the subsequent calls. You can even sign this toke with a secret to verify its authenticityRuelle
S
0

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.

Smoothtongued answered 23/5, 2020 at 3:23 Comment(0)
O
0

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:

  1. 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.

  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 because the access token is already tied to the email.

  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.

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.

Onym answered 25/5, 2020 at 19:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.