60

I found this question, which has an answer, but facebook changed the token format since then, now it is something like:

AAACEdEose0cBACgUMGMCRi9qVbqO3u7mdATQzg[more funny letters]ig8b3uss9WrhGZBYjr20rnJu263BAZDZD

In short, you cannot infer anything from it. I also found the access token debugger, which shows the information I am looking for if you paste a token in, which is nice, but does not help me do it programmatically.

Point is, if someone gets a token for a user, he can use it to access the graph, which is what I do in my application - I want to be sure that people are forwarding the token that was issued to them by my application, and not another.

My application flow is:

  1. Get access token from facebook (nothing special, in the way it is described in here , Server-side Flow. (also iPhone and android and used, but they have similar flows if I recall correctly))
    [device] <-> [facebook]
  2. With that access token, the device will access my application server with the token
    [device] <-> [Jonathan's application]
    At my server I attach the access token to the user and use that to give permissions to that user in my application. (using the facebook connect to authenticate users)


My application is secured, and the access done is also authenticated regardless of facebook, BUT! in this flow, the a weak link I identified is that I cannot authenticate for sure that the access token I got was signed for my application - I do not like it because I cache the tokens for offline use, I want to be 100% sure they are for my application, with my permissions.

So what will be the (best) way to authenticate that the token I got is related to my application (for relation to user, I use the token to access /me and see which user this token is for)

I do not need to decrypt the token (i guess its some sort of AES), I am just looking for an endpoint that will tell me the token matched my application id.

(EDIT: Using the C# SDK, if it matters.. But a graph/rest call to give that info is just as good as well :) )

Jonathan Levison
  • 2,607
  • 1
  • 16
  • 22
  • 1
    Awesome question, and great answer. That was a missing link for me as well. Thank you – Martin Wawrusch Sep 09 '12 at 19:09
  • See also http://stackoverflow.com/questions/8605703/how-to-verify-facebook-access-token – Vadzim Jul 23 '15 at 20:29
  • Possible duplicate of [Facebook access token server-side validation for iPhone app](http://stackoverflow.com/questions/5406859/facebook-access-token-server-side-validation-for-iphone-app) – rogerdpack Apr 11 '17 at 20:29

4 Answers4

64

https://graph.facebook.com/app/?access_token=[user_access_token]

This will return the app this token was generated for, you can compare that against your app's id.

rogerdpack
  • 50,731
  • 31
  • 212
  • 332
Daaniel
  • 656
  • 6
  • 3
  • Is this a documented facebook feature, or just something that happens to work at the moment? It looks like you're doing this: https://developers.facebook.com/docs/authentication/applications/ (step 2) but using a user access token rather than an app access token. Or is that the app_id, not literally 'app'? Will try. – PapaFreud Jun 15 '12 at 08:01
  • 1
    OK, I'm upvoting this because it works, but I still haven't seen this documented in the FB api. It's not the api_id, but the literal 'app' that goes in the url. The response is some JSON including the app id (it's called simply "id" in the response. Sweet! – PapaFreud Jun 15 '12 at 09:47
  • See my answer bellow for official way, rather than some sorcery that just happens to work :) – Raimundas Sakalauskas Mar 06 '17 at 13:56
25

The official graph endpoint for inspecting access tokens is:

GET graph.facebook.com/debug_token?
      input_token=[user_access_token]&
      access_token=[app_token_or_admin_token]

Example response:

{
    "data": {
        "app_id": 138483919580948, 
        "application": "Social Cafe", 
        "expires_at": 1352419328, 
        "is_valid": true, 
        "issued_at": 1347235328, 
        "metadata": {
            "sso": "iphone-safari"
        }, 
        "scopes": [
            "email", 
            "publish_actions"
        ], 
        "user_id": 1207059
    }
}

app_token_or_admin_token can be obtained using the Graph API call:

GET graph.facebook.com/oauth/access_token?
     client_id={app-id}
    &client_secret={app-secret}
    &grant_type=client_credentials

The debug_token endpoint will fail if that user_access_token doesn't belong to the app that generated the app_token_or_admin_token.

Relevant facebook documentation:

rogerdpack
  • 50,731
  • 31
  • 212
  • 332
vially
  • 1,409
  • 16
  • 18
  • I have been trying this and I either get `Unknwon OAuth 2.0 method, debug_token` or it tells me I'm missing `client_id` or `redirect_uri` if I don't include those. The official documentation still contains this step so any ideas? – Scott Salyer Apr 02 '14 at 21:23
5

A documented way to ensure this is to use appsecret_proof.

GET graph.facebook.com/v2.5/me?access_token=[TOKEN]&appsecret_proof=[PROOF]

This verifies not only that it is a valid token, but also that the token belongs to the app. It also gets you user data in one go.

You can derive PROOF above in C# using this (from here):

public static string ComputeHmacSha256Hash(string valueToHash, string key)
{
    byte[] keyBytes = Encoding.ASCII.GetBytes(key); 
    byte[] valueBytes = Encoding.ASCII.GetBytes(valueToHash);
    byte[] tokenBytes = new HMACSHA256(keyBytes).ComputeHash(valueBytes);
    valueBytes = null;
    keyBytes = null; 

    StringBuilder token = new StringBuilder();
    foreach (byte b in tokenBytes)
    {
        token.AppendFormat("{0:x2}", b);
    }
    tokenBytes = null; 

    return token.ToString();
}

ComputeHmacSha256Hash(accessToken, appSecret);
Nuno Cruces
  • 1,234
  • 13
  • 16
  • 1
    Confirmed, this is the best way. In case if appsecret_proof is generated for another app it will throw error despite valid token. Moreover, appsecret_proof can be attached to any method of API. –  Jul 19 '18 at 12:00
  • No more supported in V4.0, need to use `access_token` which is app access token – Ratul Sharker Aug 01 '19 at 09:31
4

Why not to use official way of doing things? Here's the request from FB's own video about security.

Request: https://graph.facebook.com/debug_token?input_token={token-to-check}&access_token={app_id}|{app_secret}

Response: "data": { "app_id": {token-app-id}, "user_id": {token-user-id}, ... }

Link to an official video: https://www.facebook.com/FacebookforDevelopers/videos/10152795636318553/

I made a screenshot so that time is visible, and you can find more info if you are interested.

Facebook video screenshot

Raimundas Sakalauskas
  • 1,625
  • 18
  • 22