Facebook Connect Graph API - Why Can't I Retrieve All User's Details? - facebook

I feel like every second question i ask here is relating to Facebook Connect - that says a lot about their API. Anyway, that's politics, i digress..
I'm trying to pull back user details from the Graph API for use in my application (which is an FBML external website - JavaScript SDK for authentication).
I have requested the following permissions from the user: (using the regular dialog)
publish_stream
email
This works, and allows me to post to the user's wall, and grab their email from the Graph API.
But when i do a HTTP GET Request to the following URL:
https://graph.facebook.com/uid?access_token=oat (where uid = the user id of the user i'm attempting to grab details for, and oat = the OAuth token i have).
All that comes back in the JSON is the User ID (which i already have, since im putting it in the URL), and the email.
Why can i not get things like first name, last name, locale, etc?
Am i using the wrong URL? Is my OAuth token wrong?
I'm getting the OAuth token from here:
https://graph.facebook.com/oauth/access_token?type=client_cred&client_id=myappid&client_secret=myappsecret
UPDATE:
It looks like the issue is my OAuth token.
Because when i go to the docs: http://developers.facebook.com/docs/api
And use the sample OAuth Token for the user im trying to retrieve, it gets all the details.
Anyone know what is wrong with my OAuth token call?

So, i was using the wrong URL for the OAuth Exchange. It needed to be this:
https://graph.facebook.com/oauth/exchange_sessions?type=client_cred&client_id=myappid&client_secrete=myappsecret&sessions=userseshid
The URL that i WAS using was as per the doco, the above one that works is nowhere to be found.
I'm at the point with FBC that i no longer care about the how, if it works, be thankful that it does even that and move on.
EDIT:
Also, i was wondering why the Graph API calls would "stop" working for no reason.
The answer is i needed to compare the Session Key used to obtain the OAuth token, with the Session Key currently in the cookies. If they are different, i needed to get a new OAuth token.
The session key used for any OAuth token is part of the actual OAuth token:
aaa|bbbb|cccc
Where bbbb is the session key. So i just compare that before doing any Graph API calls.

Related

REST API for website which uses Facebook for authentication

We have a website where the only way to login and authenticate yourself with the site is with Facebook (this was not my choice). The first time you login with Facebook, an account gets automatically created for you.
We now want to create an iPhone application for our site and also a public API for others to use our service.
This question is about how to authenticate with our website from the app/API and is broken into 2 parts:
What is the correct way to handle REST authentication from an API to a website which only uses Facebook OAuth as an authentication method?
I have read and researched a lot about standard methods of authentication for REST API. We can't use such methods as Basic Auth over HTTPS, as there are no credentials for a user as such. Something like this seems to be only for authenticating applications using the API.
Currently, the best way I can think is you hit an /authorize end-point on our API, it redirects to Facebook OAuth, then redirects back to the site and provides a 'token' which the user of the API can use to authenticate subsequent requests.
For an official application that we create, we wouldn't necessarily need to use the public API in the same way. What would be the best way then to talk to our website and authenticate users?
I understand (I think) how to authenticate 3rd-party applications that are using our API, using API (public) keys and secret (private) keys. However, when it comes to authenticating the user who is using the app, I am getting rather confused about how to go about it when the only way we have to authenticate a user is Facebook.
I feel like I'm missing something very obvious, or don't fully understand how public REST APIs should work, so any advice and help would be greatly appreciated.
UPDATE: see below
I've been thinking hard about this question too. It's not entirely clear to me yet but here's the route I am thinking of going. I am creating a REST API an my users only auth with Facebook connect.
On the CLIENT:
Use the Facebook API to login and get an OAUTH2 code.
Exchange this code for an access token.
In every call to my custom API I'll include the Facebook user id and the access token.
On the API (for every method that requires user authentication):
Make a request to the /me Facebook graph using the access token from above.
Verify that the Facebook user id returned matches the user id passed to my API from above.
If the access token has expired additional communication is required.
I have yet to test this. How does it sound?
--- Update: July 27th, 2014 to answer question ---
I only use the above exchange once upon login. Once I determine which user is logging in, I create my own access token, and that token is used from that point going forward. So the new flow looks like this...
On the CLIENT:
Use the Facebook API to login and get an OAUTH2 code.
Exchange this code for an access token.
Request an access token from my API, including the Facebook token as a parameter
On the API
Receive access token request.
Make a request to the /me Facebook graph using the facebook access token
Verify that the Facebook user exists and match to a user in my database
Create my own access token, save it and return it to the client to be used from this point forward
This is my implementation using JWTs (JSON Web Tokens), basically similar to Chris' updated answer. I have used Facebook JS SDK and JWT.
Here's my implementation.
Client: Use Facebook JS SDK to log in and get the access token.
Client: Request JWT from my API by calling /verify-access-token endpoint.
MyAPI: Receives access token, verify it by calling /me endpoint of Facebook API.
MyAPI: If access token is valid, finds the user from database, logs in the user if exist. Create a JWT with required fields as payload, set an expiry, sign with the secret key and send back to the client.
Client: Stores the JWT in local storage.
Client: Sends the token (the JWT from step 5) along with the request for the next API call.
MyAPI: validate the token with the secret key, if token is valid, exchange the token for a new one, send it back to the client along with the API response. (No external API calls for verification of the token here after) [if the token is invalid/expired request client to authenticate again and repeat from 1]
Client Replaces the stored token with the new one and use it for the next API call. Once the token expiry is met, the token expires revoking access to API.
Every token is used once.
Read more answers about security and JWT
How secure is JWT
If you can decode JWT how are they secure?
JSON Web Tokens (JWT) as user identification and authentication tokens
I am trying to answer the same question and have been going through a lot of reading recently...
I won't have "the" answer but things are getting a little clearer for me. Have you read the comments in the article you mentioned? I found them really interesting and helpful.
As a result, and in the light of how things have evolved since the first article has been written, here's what I think I'll do:
HTTPS everywhere — this allows you to forget about HMAC, signing, nonce, ...
Use OAuth2:
When authentication requests come from my own apps/website, use this 'trick' (or a variation of it) described in a reply to the article mentioned before.
In my case, I have two types of users: those with classic login/password credentials and those who have signed up with Facebook Connect.
So I'd provide a regular login form with a "Login with Facebook" button. If the user logs in with his "classic" credentials, I'd just send these to my OAuth2 endpoint with a grant_type=password.
If he chooses to log in via Facebook, I think that would be a two-steps process:
First, use Facebook iOS SDK to open an FBSession
When that's done and the app is given back control, there should be a way to get a Facebook ID for that user. I'd send this ID alone to my OAuth2 endpoint with an extension grant understood by my server as "using an FB User ID".
Please note that I am still heavily researching on all this stuff, so that might not be a perfect answer... maybe not even a correct one! But I think that would make for a good starting point.
The idea of using an "extension grant" for the Facebook authentication might involve having to register it to do things properly? I'm not quite sure.
Anyway, I hope I was able to help you even a bit, and that at least it can start a discussion to find the best solution to this problem :)
Update
The Facebook login is not a solution as pointed in the comments: anybody could send an arbitrary user ID and log in as this user on the API.
What about doing it like this:
Show a login form with a "Facebook login" button
If this login method is chosen, act kinda like the Facebook SDK: open a web page from your authentication server, which will initiate the Facebook login.
Once the user has logged in, Facebook will use your redirect URL to confirm; make that URL point to another endpoint of your authentication server (possibly with an extra parameter indicating the call came from an app?)
When the authentication endpoint is hit, the authentication can securely identify the user, retain its FB User ID/FB Session and return an access token to your app using a custom URL scheme, just like the Facebook SDK would do
Looks better?

Confirming a Facebook Access Token?

We're using the Facebook JS SDK to authenticate users to our application, then sending that information to the server back end to log our user into the application (we support multiple forms of authentication but we can only support FB using a client side flow).
FB is able to log in correctly, I'm able to authenticate the user and everything else, but there's one wrinkle that I'm not sure how to handle, and I'm having difficulty finding anything in the documentation about it. Facebook sends back an accessToken in addition to an id. My question is, how do I verify on the server side that the accessToken is correct for the given id? I want to make sure that the data the user sends us matches what Facebook sent them, and I can't imagine this is that out of the ordinary, yet I can't seem to find any documentation on it.
In the response from Facebook should be a signed_request string that can authenticate that the data is genuine with and decoded to yield the user id and an oauth token for the user.
Passing this along with the other response to your server-side code should allow you to validate everything pretty easily.
May I suggest this answer from another question! It uses try-catch. It is probably the only way to verify that the authentication and the permissions are valid! That's how they do in their examples
Facebook OAuthException: (#1)
I dont think facebook provides any other way of checking

User Data from Facebook WITHOUT SDK

I have the access token from the user, and I want to retrive the data from their profile. I am working on Unity3D c# therefore I can not use any SDK.
Is there a way of getting it trough a graph request?
I've already tried with
https://graph.facebook.com/me?access_token=00000000000000|AAAAAAAAAAAAAAA
but throws me an error like this..
"message": "An active access token must be used to query information about the current user.",
When I ask for permissions I ask the user to allow me the publish_stream and to access profile data.
How do I get an active access token? I just want the UserID.
Thanks for your answers, and sorry for my terrible english.
So I wanted ti get the User UserAgent Token the only thing that you must do is add that parameter to the Access URL in my case
https://graph.facebook.com/oauth/authorize?type=user_agent&client_id=000000000000000&redirect_uri=http://yourRedirectdomain.com&scope=user_photos,email,user_birthday,offline_access,plublish_stream
Facebook will redirect you to the redirect_uri URL, and the access token will be given in form of a hash. Extra Tip: Yo have to access the Hashed token vía Javascript,
var hash = document.location.hash;
var n=hash.split("=");
This is one method, Im sure there is a better one.
Thank everybody for the answers!
you're Graph Call / HTTP request looks about right.
I'm guessing, based on the error, that the access token has expired.
Normally, they last for about 1-2 hours since the last time they were used. (If i recall correctly). So, a user will start using a website, and the website can make graph calls with the access token while the user is actually using the website for that session, but the token will expire soon after that.
However, you can also ask Facebook for a longer lasting access_token, which will last for approximately 60 days.
Check here for some info :: http://developers.facebook.com/roadmap/offline-access-removal/
As it stands, trying to find this info through browsing the developer docs in Facebook is rather difficult, if not impossible. :-/
You can’t query the API for /me with an app access token, since the API has no way of knowing who “me” is supposed to be.
Only user access tokens contain the info which user id they apply to, and hence only those can be used to query /me successfully.

Getting and storing access tokens using base_facebook.php and facebook.php?

Using the above libraries, I can get the details of a user, his authorisation, his friends, but only once: I need to store the access_token and key in database, so the user can access his friends walls or other public details.
Can anyone help?
(I have used OAuth for Twitter and Tumblr, but I can't get it for FB).
https://developers.facebook.com/docs/authentication/
Be careful with saving the token. When not requesting all-time permission, it expires in a certain time (what might be your problem)
When using a canvas app (the ones integrated in apps.facebook.com) requesting another token is quite simple. Facebook posts a signed_request parameter to your app whenever a user accesses it (https://developers.facebook.com/docs/authentication/signed_request/).
Decode it, pass it to the Graph API, profit.
if you need a generic access_token without a login... you can use $appID ."|". $secKey
this is called a APP access token, so it would be logged in as the "Application" not a user
!!! make sure you use this on https://graph.facebook.com/ !!!
hints the "https://" for secure SSL connection
but the API already determines this.

Facebook Javascript API: matching a login to a user

When using the Javascript API login, it returns to the page with a number of parameters, like the access token, the user ID, and other details. If I wanted to associate a user in my database with this Facebook user, which would be the piece of data I want to store to be able to look it up later for authentication?
In other words, which token should I store, so that next time the user logs in, I can look in the database for this token and authenticate the user?
I would use the UID, but it seems easy to spoof another UID and impersonate someone else.
Thanks!
Client side spoofing is not your concern. If you are displaying FB content based upon FB authentication, then FB is responsible for the integrity of that process.
If you are using this info server side, then you need to follow the OAuth 2.0 flow which is not spoofable (to my knowledge) because you are going directly to FB for authentication.
You can't mix the two flows because you leave yourself vulnerable to attacks.
And to answer your other question, yes, you should link your DB to the UID because the access_token will change.
You can validate the fb access token with the fb js sdk. So you can take the fb-uid as save. The tokens you get from fb are only valid for a limited time, so you shouldn't save them.
UPDATE:
Regarding the saveness of the fb-uid: Your PHP script gets a signed request from facebook. That request is signed with your app's secret so that no one else can read that data. The request contains a fb-session for the current user (including the uid) and an access token.