I am implementing a manual flow for facebook login in our reactjs + meteor app. As of now I have got the code which FB sends in redirect url to my site.
Using this code I was able to make graph api call as shown here. Then I whitelisted my server IP in the facebook app. Even this works good. I'm able to get an access token by exchanging the code. Below is the code that works here:
const accessToken = await HTTP.get('https://graph.facebook.com/v2.10/oauth/access_token?client_id=<appID>&redirect_uri=mysite.com/facebook/redirect&client_secret=<appSecret>&code=<code>');
But when I enable app secret proof, my graph call returns oauth error code 1 which specifies facebook could not validate app secret. I referred this document to check on how to create & pass the app secret proof. I tried generating the app proof by passing code & app secret, one at a time. Below is how I am trying to get an access token:
const appSecProof = cryto.createHmac('sha256', <appSecret>).update(<code>).digest('hex');
//<appSecret> is the appSecret from FB App, <code> is the code I get from FB after FB redirects to my site.
const accessToken = await HTTP.get('https://graph.facebook.com/v2.10/oauth/access_token?client_id=<appID>&redirect_uri=mysite.com/facebook/redirect&client_secret=<appSecret>&code=<code>&appsecret_proof=<appSecProof>');
I am configuring the app right for app secret proof?
The other thought I am getting is if I am doing a manual server side implementation then IP whitelisting alone can take care of security & I don't need to enable app secret proof.
My end goal is to implement a secure the facebook login. I had tried with facebook javascript SDK which works good. But when testing I found it shows the access token in browser network panel's xhr calls. Using this access token I could make a GET call to FB API using postman. So wanted to have all communication from server side.
Thanks.
Related
I'm just looking at migrating an existing Login with Facebook flow over to Sign in with Apple with the hope of eliminating FB Login entirely from our iOS app.
The client side seems straight forward enough, however there's one topic I can't seem to see any documentation or discussion on Stack Overflow about - a Sign In with Apple equivalent for FB App Access Tokens.
Facebook Login supports different token types (https://developers.facebook.com/docs/facebook-login/access-tokens/) and currently our app back end supports 2 authentication flows.
From End App Users, they Login with Facebook, send the provided client User Access Token to the app backend which validates the token against Facebook and then issues an app specific JWT token to the app client that is used in further app API calls until expiry.
From backend server components. These request an App Access Token from Facebook e.g.
curl -X GET "https://graph.facebook.com/oauth/access_token
?client_id={your-app-id}
&client_secret={your-app-secret}
&grant_type=client_credentials"
The App Access Token is then send to the app backend which validates the token against Facebook and then issue an app specific JWT token that is used in further server to server API calls until expiry.
Replacing 1 above seems straightforward but what about 2? Is there a mechanism for achieving the same flow with Sign In with Apple?
It seems like the https://developer.apple.com/documentation/signinwithapplerestapi would be the API to use for validation but is there a way to generate an App Access Token equivalent for Sign In with Apple in the first place to validate using this REST API?
Thanks
I think it's possible
I'm not exactly sure how to really use it or validate it yet, but you get an access_token in the response from https://appleid.apple.com/auth/token when Generating and Validating Tokens
Getting an access_token from Apple
This example assumes you have an Authorization Grant Code, but the same is possible if you have a refresh_token, etc. instead.
Prepare a POST request to https://appleid.apple.com/auth/token
Fill out the following key-values as x-www-form-urlencoded:
client_id
client_secret
code
grant_type
redirect_uri
If successfull, this will return:
**access_token**
token_type
expires_in
id_token
I'm not sure if this is the type of access_token you're looking for, but I wanted to bring it to your attention.
It may be useless for now
After writing this, I came across this thread in the forums where Apple said:
Currently, the access token only indicates a successful refresh token validation. There are currently no endpoints where it can be used and it is reserved for future use. So, it can be ignored for now.
I have an Ember.js app using Ember Simple Auth. The API returns an auth token on successful sign in with email and password. I'm trying to add Facebook Login using their Javascript SDK. Upon successful sign in with Facebook, I would like to post the Facebook access token back to our API, so that the API can store the access token and respond with our own auth token. However, I'm not sure how to connect this to Ember Simple Auth so that the auth token can be stored outside of the normal email/password sign in. What do I need to do in order to make this work?
The dummy app in the repository implements the exact functionality you're describing (except it uses torii instead of the Facebook JS SDK). If you're using Rails on the server you might find the RailsApiAuth engine helpful that already implements the server part for the Facebook auth code flow.
I managed to develop a Azure Mobile Service and an iOS application which connects to my service using Facebook authentication. Everything works perfectly fine from the app.
Now I'm trying to access my mobile service from a regular HTTP REST client and I'm hitting authentication issues. I tried to get the authentication code from FB and set the code in X-ZUMO-AUTH header but this does not help. I still get the "Authorization has been denied for this request" error.
I would really appreciate if someone could point to the right direction on how to mimic the access to the mobile service just like the iOS app is doing it.
Thanks,
Ruben
The token you must supply as the 'X-ZUMO-AUTH' is not the access token that facebook send back to you; it is the token that your mobile service backend send back to you.
In order to get a valid token, access the following url in your browser 'https://mymobileserviceurl/login/facebook'. Then fill your facebook infos and you should be redirected to a page which url looks like 'https://mymobileserviceurl/login/done......'. This url contains a 'authenticationToken' parameter. This is the value you have to paste in your 'X-ZUMO-AUTH' header. (should begin with 'ey' and avoid copying ASCII chars)
In your application, in order to get the right token, you should call MobileServiceClient.LoginAsync.
It is suggested that whether your app uses code or token as your response_type you should perform an automated check on the access_token to confirm that the token belongs to the person the app expects it to belong to and that it was your app that generated the token.
You are supposed to do this on
GET graph.facebook.com/debug_token?
input_token={token-to-inspect}
&access_token={app-token-or-admin-token}
where app-token is app_id|app_secret and token-to-inspect is the user's access_token. Also, I think from reading the documentation you can retrieve an app-token by doing a client-credentials call with the app_id and app_secret.
This is fine with an authorization flow implemented server-side, but what if you're using the implicit method and chose response_type as token (and for whatever reason aren't using FB's javascript SDK)? How do you safely get that app-token without leaking your app_secret? How does FB's SDK do it?
You can generate an app_token in your Facebook developer panel here
and then simply save it into a config file server side. From the developer's page:
App tokens do not expire and should be kept secret as they are related to your app secret.
On my page, I use the following flow:
The user authenticates with the Facebook JS SDK, and then sends his
token + uid to the server.
The server validates that the given token
is related to the given person via a call to the "debug_token"
method, that you spoke of.
If the token + uid combination is valid,
it authenticates the user server side.
I hope this helps.
I am working on a product which has both a desktop web site and a native iOS application. We are providing Facebook connect as a login option for our users in both contexts.
My intention was to share the same Facebook tokens via a secure JSON API for use in both contexts: when a user signs in on the web, the token is stored to our backend so that when the mobile client next runs, it can download the token and use it as well, and vice-versa. (* The detailed reasoning for this approach I explain at the end of the question, and is not essential to the question.)
The problem: when the iOS client uses a token to preset a feed dialog, if that token is generated by the web using the server-side flow, the dialog webview renders an error:
"An error occured with {my app name}. Please try again later."
This is reliably reproducible:
Generate a new access token using the server-side flow. Make sure you request publish_actions permission since you'll be using the feed dialog.
Using an incognito browser window (to get an empty cookie jar), view the m.facebook.com page that the iOS feed dialog would render in its webview: https://m.facebook.com/dialog/feed?access_token=SERVER_SIDE_FLOW_ACCESS_TOKEN&app_id=YOUR_APP_ID&redirect_uri=fbconnect%3A%2F%2Fsuccess&sdk=2&display=touch
Alternatively to #2 you could do all the work (which I have done already) of creating a dummy iOS app with the Facebook SDK, instantiating it correctly and presenting the dialog. It's just easier to go straight to the m.facebook.com feed URL for the purposes of reproducing the error.
If the token was generated by the auth flow initiated by the native Facebook iOS SDK instead of the server-side auth flow, the above feed url works perfectly fine, as expected.
Additionally, either token (mobile or server generated) works perfectly fine for posting feed items directly via the graph api. The problem is really just with the mobile feed dialog.
Is Facebook intentionally disallowing server-side generated tokens from operating in mobile feed dialog contexts?
Is this a bug with the feed dialog endpoint on m.facebook.com?
Or, hopefully, am I doing something wrong?
Why do I want to share tokens?
Since the offline_access permission is being removed, each client (web vs mobile) can benefit from having the other client refresh the same token when the user is active. This will lead to fewer instances of token expiry, and therefore fewer cases in which users must re-authenticate from scratch.
Likewise, users are not asked so frequently to approve additional permissions, since each client can benefit from the other's permission augmentations.
The tokens you get from the server side auth are different from the ones on the client side (I look at iOS/Android as client).
The server tokens are long lived one (60 days) while the client ones are short lived (a few hours).
The server side flow adds another layer of security where your servers authenticate against the facebook servers, which is probably why you get a long lived token automatically when using this flow.
If you try the debugger with an access token you will receive information about the token, such as the "origin" of the token.
For example a token generated from a client side auth (using js) has "Origin: Web".
That means that facebook indeed differentiate between tokens.
I'm not 100% sure about this, but from what you're saying it does sound like facebook is limiting the UI to the usage of client tokens and not server side ones, probably because the dialogs let the user do things without the need of the app to get permissions, and so if you have a 60 days token your app can then use it instead of the user and do things on his behalf with out having his permission.
I'm just guessing here.
What I would recommend you is to use the server token only on the server side, and let the iOS client handle his own token.
According to the Handling Invalid and Expired Access Tokens guide, it states:
iOS native applications
API errors are handled by the FBRequestDelegate interface. When you
detect an access token is invalid or has expired, your application
will need to multi-task over to the Facebook iOS app. Assuming the
user has not deauthorized your app, they will be immediately
multi-tasked back to your iOS application with a fresh, valid access
token.
Which means that you don't have to worry about the token getting expired on the client side.