14

I need to verify that users on my iPhone app are actually logged in to my Facebook app. I'm able to verify their user id by retrieving it with their Access token:

https://graph.facebook.com/me?fields=id&access_token=XXXXXXXXXXXXXXX

The security issue I foresee is that, they can send me any valid access token, and it will return their user id. I need to also validate this token is for my specific app. Is there a way to return the Application ID in this request to validate that?

Eric Di Bari
  • 3,609
  • 7
  • 36
  • 48
  • I am confused. Why are you taking an external token? And more importantly, how are you asking the users to give it to you? Passing token around is a security issue - if someone gets their hand on it, they can impersonate the user and your application. You should be using the FB iOS SDK to ask the user to login to Facebook from inside your app instead. – Franci Penov Jan 27 '13 at 03:16
  • I am. They log into my facebook app on my iphone app. The problem is that some actions must be completed/verified on the server through my API. Since facebook is the authentication/identity management system for my app, when they make certain API calls to my server, I need to verify that the user is who they say they are. They pass their user id and access token and I verify it on the server. – Eric Di Bari Jan 27 '13 at 03:21
  • 1
    I see. It's an interesting scenario. Would you mind sending me a short email to francip at fb.com about this? I want to make sure the SDK folks are thinking about identity transfer between client and server apps. – Franci Penov Jan 27 '13 at 03:28
  • possible duplicate of [Get application id from user access token (or verify the source application for a token)](http://stackoverflow.com/questions/8141037/get-application-id-from-user-access-token-or-verify-the-source-application-for) – Gajus Aug 09 '14 at 15:16

4 Answers4

21

Facebook now provides support for debugging an Access Token. You can retrieve the information related to a particular Access Token by issuing a GET request to the debug_token connection. Something like:

GET /debug_token?
     input_token={input-token}&
     access_token={access-token}

Where, input-token: the access token you want to get information about and access-token: your app access token or a valid user access token from a developer of the app

And this will return the following information:

{
        "data": {
            "app_id": 000000000000000, 
            "application": "Social Cafe", 
            "expires_at": 1352419328, 
            "is_valid": true, 
            "issued_at": 1347235328, 
            "scopes": [
                "email", 
                "publish_actions"
            ], 
            "user_id": 1207059
        }
    }

You can get more information about it in the Getting Info about Tokens and Debugging reference.

Rahil Arora
  • 3,486
  • 3
  • 23
  • 41
14

Yes. You can query this:

https://graph.facebook.com/app?access_token=TOKEN

It will return the name, id and several stats about the app that created the access token.

cpilko
  • 11,674
  • 2
  • 28
  • 45
  • So to check that a user's access token belongs to my app, I'll need to make two API requests to Facebook? – Eric Di Bari Jan 27 '13 at 03:11
  • 1
    Not necessarily. You can do it in one API request using a [batch request](https://developers.facebook.com/docs/reference/api/batch/) – cpilko Jan 27 '13 at 03:13
  • You could also do it using an [FQL multiquery](https://developers.facebook.com/docs/technical-guides/fql/#multi) on the `user` and `application` tables. You can do FQL in a simple `GET` request. – cpilko Jan 27 '13 at 03:18
  • Life saver! This check would not be necessary if Facebook used constant user IDs , like Google do. –  Jul 19 '18 at 10:05
1

Here is my implementation in Python 3, implementing a single Facebook Batch Request. This should get you both the APP and USER data that is tied to the user's access_token, in one call.

#Build the batch, and urlencode it
batchRequest = '[{"method":"GET","relative_url":"me"}, {"method":"GET","relative_url":"app"}]'
batchRequestEncoded = urllib.parse.quote_plus(batchRequest)

#Prepare the batch and access_token params
dataParams = 'access_token=%s&batch=%s' % (fb_access_token, batchRequestEncoded)
dataParamsEncoded = dataParams.encode()
fbURL = 'https://graph.facebook.com/'

#This will POST the request
response = urllib.request.urlopen(fbURL, dataParamsEncoded)

#Get the results
data = response.read()
data = json.loads(data.decode("utf-8"))

There is probably a more pythonic way to implement some of the encoding calls I wrote, but I just wanted to show what exactly worked for me.

Sagan
  • 1,043
  • 1
  • 10
  • 9
0

You can use appsecret_proof on your api calls.

From the official documentation:

Access tokens are portable. It's possible to take an access token generated on a client by Facebook's SDK, send it to a server and then make calls from that server on behalf of the client.

You can prevent this by adding the appsecret_proof parameter to every API call from a server and enabling the setting to require proof on all calls. This prevents bad guys from making API calls with your access tokens from their servers.

Example:

https://graph.facebook.com/app?access_token=TOKEN&appsecret_proof=<app secret proof>

In PHP:

$endpoint = sprintf(
    'https://graph.facebook.com/app?access_token=%s&appsecret_proof=%s',
    urlencode($accessToken),
    urlencode(
        hash_hmac('sha256', $accessToken, $appSecret)
    )
);

You can now trust that the response that you got can be used for authentication.

Federkun
  • 30,933
  • 8
  • 62
  • 80