113
votes

I'm developing iPhone application, that is based on communication with server, and I want to use Facebook authentication mechanisms.

Basically, I think it should work like this:

  1. In my iPhone app, user logs in to Facebook, using his email and password.
  2. User allows access to his data for related Facebook application.
  3. My iPhone app receives access token, after successful log in.
  4. In further communication with my server, my iPhone application should use the received Facebook access token (for example: in queries).
  5. When my server receives some query from iPhone app, with access token, it should ask Facebook that this token is valid (and for who), and if yes, server should assume that user is authenticated with Facebook.

My question is: how the server should ask Facebook if given access token is valid? I think I should somehow check if the token is valid for my Facebook app.

I've tried many Facebook queries to graph API, that I've found, but nothing worked as I expected. Can you provide me some example?

8
Unless the user has logged out of the app in FB, you can just send the auth token across to the server (ssl hopefuly). Does a simple query of "/me" via the graph api succeed or fail?The Mad Gamer
you will get message in response from facebook that your token is not valid :)Jean-Luc Godard
I'm trying to do something very similar to what you're doing. You never marked this question as answered, did you ever get this working?tempy
What happens when the access_token expires ? should we ask user to login again ? i want to understand how to re validate again after token is expireddebianmaster
@debianmaster it depends on your app architecture. If you consider the case "no FB token - no access to the app", than yes, log out the user. Otherwise, you might consider an "unlink" logic, where user stays logged in, but the info, received from Facebook is detached from his account on the server/client.Yevhen Dubinin

8 Answers

116
votes

Here's a two step process you can use to validate that a user access token belongs to your App:

1) Generate an App Access token

(https://developers.facebook.com/docs/howtos/login/login-as-app/)

https://graph.facebook.com/oauth/access_token?
client_id=YOUR_APP_ID
&client_secret=YOUR_APP_SECRET
&grant_type=client_credentials

2) Debug the User Access token

(https://developers.facebook.com/docs/howtos/login/debugging-access-tokens/)

https://graph.facebook.com/debug_token?
input_token=INPUT_TOKEN
&access_token=ACCESS_TOKEN

Where INPUT_TOKEN is the user access token you want to verify, and ACCESS_TOKEN is your app's token that you got from step 1.

The debug endpoint basically dumps all information about a token, so it'll respond with something like this:

{
    data: {
        app_id: YOUR_APP_ID,
        is_valid: true,
        metadata: {
            sso: "iphone-safari"
        },
        application: YOUR_APP_NAMESPACE,
        user_id: USER_ID,
        issued_at: 1366236791,
        expires_at: 1371420791,
        scopes: [ ]
    }
}

If that token isn't from "your app" then it will return an error response.

114
votes

Update: this answer seems insecure since it doesn't validate the token first as belonging to your app, see the comments, original answer as follows:

I assume that you already have the access token in hand. In such a case the simplest way to validate an access token is to issue the following request

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

Here replace @accesstoken with the access token you have. I will breakdown the url and will explain each.

We are issuing a graph api request here which will return the Facebook User Id of the owner of the access token as a JSON string. The keyword 'me' represents the currently logged in user or the owner of the access token. For this request access token is a mandatory parameter.

If the provided access token is not valid or expired Facebook will just return an error message of some sort.

For a valid access token the result will somehow look like this

{
   "id": "ID_VALUE"
}
11
votes

Another solution would be to use https://graph.facebook.com/app/?access_token=[user_access_token] as described by Get application id from user access token (or verify the source application for a token).

This appears to be an undocumented feature, but returns JSON containing the id of the app the token was generated for. If the token wasn't for your app, it returns a 400.

6
votes

In the latest version of facebook (2.2) you can do it this way:

https://developers.facebook.com/docs/graph-api/reference/v2.2/debug_token

Sample output:

{
    "data": {
        "app_id": "THE APP ID", 
        "application": "APP NAME", 
        "expires_at": 1427245200, 
        "is_valid": true, 
        "scopes": [
        "public_profile", 
        "basic_info", 
        "read_stream", 
        "email", 
        "publish_actions", 
        "read_friendlists", 
        "user_birthday", 
        "user_hometown", 
        "user_location", 
        "user_likes", 
        "user_photos", 
        "user_videos", 
        "user_friends", 
        "user_posts"
        ], 
        "user_id": "THE USER ID"
    }
}
2
votes
private function facebookRequestMe($access_token)
{
    include_once "facebook.php";

    $facebook = new Facebook(array(
        "appId" => "your_application_id",
        "secret" => "your_application_secret"
    ));
    $facebook->setAccessToken($access_token);
    return $facebook->api("/me", "GET");
}

You can download the Facebook SDK for PHP from GitHub.

2
votes

If a user has passed you a Facebook UID that they claim is theirs and you want to check if it's legit, this is a Python function that will verify it against their access token (an implementation of Robin Jome's answer):

def verify_facebook_id(id, access_token):
    import requests
    import simplejson
    params = {'fields': 'id', 'access_token': access_token}
    text = requests.get("https://graph.facebook.com/me", params=params).text
    json = simplejson.loads(text)
    response_id = json["id"]
    return response_id == id
1
votes

This is the only secure method to verify user token using just one request:

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

Note that a sign "|" in the above URL isn't used as OR but as separator and must be there after fill the other fields.

The response will be JSON looking like that:

{
    data: {
        app_id: {app_id},
        application: {app_name},
        expires_at: {some_number},
        is_valid: {true|false}
        scopes: {array_of_permissions},
        user_id: {user_id}
    }
}

Reference: https://developers.facebook.com/docs/facebook-login/access-tokens/#apptokens (above method is mentioned at the bottom of this section)

-1
votes

Along with an access token Facebook also sends an "expires_in" parameter, which is an offset value. Use that to compute for when the access token will expire as an NSDate. Then when you need to do a request compare the current date with the expiration date.

Also try to inspect the status codes and response strings Facebook sends back.