Buffer

How-To: Handle expired access tokens

by M. Dorn on May 16, 2011 · 0 comments

One of the most frequently asked for “How-To” requests from developers is how to handle invalid access tokens. Access tokens for users can become invalid due to various reasons. In most cases, they can expire if it’s past the time specified by the ‘expires’ field (by default access token have a 2 hour lifetime). What many developers do not realize is that an access token can also expire if a user changes her password, logs out or if she de-authorizes the app via the App Dashboard. It is very important that your apps handle such situations. If your access token expires, you need to reacquire a valid access token.

This post will walk you through how you can ensure that you are handling and recovering from these situations gracefully. It assumes that you are familiar with our server-side authentication flow.

We will discuss 4 different scenarios:

  1. The token expires after expires time (2 hours is the default).
  2. The user changes her password which invalidates the access token.
  3. The user de-authorizes your app.
  4. The user logs out of Facebook.

Token expires after expires time

This scenario refers to the use case where a user has authorized your app in the past, but the access token that you were issued has expired.

When you try to make Graph API call on her behalf you will get an HTTP 400 with the following error in the body:

{
  error: {
    type: "OAuthException",
    message: "Session has expired at unix time
      SOME_TIME. The current unix time is SOME_TIME.”
  },
}

Scenario 2: User changes her password

This scenario refers to use case where a user has authorized your app in the past and then she changes the password associated with her Facebook account. In this scenario, when you try to make Graph API call on her behalf you will get an HTTP 400 with the following error in the body:

{
  error: {
    type: "OAuthException",
    message: "The session has been invalidated because
      the user has changed the password.",
  },
}

Please note that you will receive this message even if your app was granted the offline_access permission if the user changed their password.

Scenario 3: User de-authorizes your app

This scenario refers to a use case where a user has authorized your app in the past, but then she de-authorizes your app by going to the App Dashboard. In this scenario when you try to make a Graph API call on her behalf you will get a HTTP 400 with the following error in the body:

{
  error: {
    type: "OAuthException",
    message: "Error validating access token: USER_ID
      has not authorized application APP_ID",
  },
}

Please note that even if the user had authorized your app with the offline_access permission access tokens will become invalid if the user de-authorizes your app.

Scenario 4: User logs out of Facebook

This scenario refers to a use case where a user has authorized your app in the past and then she logs out of Facebook. If the user authorized your app with the offline_access permission then the Graph API call works as expected. If the user did not grant this permission and you try to make a Graph API call on behalf of the user, you will get an HTTP 400 with the following error in the body:

{
  "error": {
    type: "OAuthException",
    message: "Error validating access token:
      The session is invalid because the user logged out."
   }
}

Solution (for all scenarios)

To ensure the best experience for your users, your app needs to be prepared to catch errors for the above scenarios. The following PHP code should you how to handle these errors and retrieve a new access token.

<?php
  $app_id = "YOUR_APP_ID";
  $app_secret = "YOUR_APP_SECRET";
  $my_url = "YOUR_POST_LOGIN_URL";

  // known valid access token stored in a database
  $access_token = "YOUR_STORED_ACCESS_TOKEN";

  $code = $_REQUEST["code"];

  // If we get a code, it means that we have re-authed the user
  //and can get a valid access_token.
  if (isset($code)) {
    $token_url="https://graph.facebook.com/oauth/access_token?client_id=
      . $app_id . "&redirect_uri=" . urlencode($my_url)
      . "&client_secret=" . $app_secret
      . "&code=" . $code . "&display=popup";
    $response = file_get_contents($token_url);
    $params = null;
    parse_str($response, $params);
    $access_token = $params['access_token'];
  }

  // Attempt to query the graph:
  $graph_url = "https://graph.facebook.com/me?"
    . "access_token=" . $access_token;
  $response = curl_get_file_contents($graph_url);
  $decoded_response = json_decode($response);

  //Check for errors
  if ($decoded_response->error) {
  // check to see if this is an oAuth error:
    if ($decoded_response->error->type== "OAuthException") {
      // Retrieving a valid access token.
      $dialog_url= "https://www.facebook.com/dialog/oauth?"
        . "client_id=" . $app_id
        . "&redirect_uri=" . urlencode($my_url);
      echo("<script> top.location.href='" . $dialog_url
      . "'</script>");
    }
    else {
      echo "other error has happened";
    }
  }
  else {
  // success
    echo("success" . $decoded_response->name);
    echo($access_token);
  }

  // note this wrapper function exists in order to circumvent PHP’s
  //strict obeying of HTTP error codes.  In this case, Facebook
  //returns error code 400 which PHP obeys and wipes out
  //the response.
  function curl_get_file_contents($URL) {
    $c = curl_init();
    curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($c, CURLOPT_URL, $URL);
    $contents = curl_exec($c);
    $err  = curl_getinfo($c,CURLINFO_HTTP_CODE);
    curl_close($c);
    if ($contents) return $contents;
    else return FALSE;
  }
?>

Ankur Pansari, a Partner Engineer, hopes this how-to post helps you handle invalid access token scenarios gracefully.

Source: Facebook Developer Blog

Related Posts with Thumbnails

Leave a Comment