Search code examples
facebookauthenticationcookies

Server side flow example


At the bottom is a working example of server side flow. It is a file fb_server_side_flow.php that I prepared from a template I found on developers.facebook.com. My first question is what exactly is $code = $_REQUEST["code"]; doing? Is it getting a Facebook cookie? If so how is $code = $_REQUEST["code"]; different from the code directly below? Is it really necessary to use session_start at towards the top of fb_server_side_flow.php?

Mainly I am trying to implement a system that gives my user an OPTION to login via Facebook but a login via Facebook is not a requirement. Is there any documentation available on implementing a login via Facebook OPTION as opposed to a required login via Facebook?

Thank you!

....
function get_facebook_cookie($app_id, $app_secret) {
  $args = array();
  parse_str(trim($_COOKIE['fbs_' . $app_id], '\\"'), $args);
  ksort($args);
  $payload = '';
  foreach ($args as $key => $value) {
    if ($key != 'sig') {
      $payload .= $key . '=' . $value;
    }
  }
  if (md5($payload . $app_secret) != $args['sig']) {
    return null;
  }
  return $args;
}

$cookie = get_facebook_cookie(YOUR_APP_ID, YOUR_APP_SECRET);
....

fb_server_side_flow.php
<?php 

   $app_id = "****";
   $app_secret = "****";
   $my_url = "http://www.sepserver.net/dsg/fb_server_side_flow.php";

   session_start();
   $code = $_REQUEST["code"];

   if(empty($code)) {
     $_SESSION['state'] = md5(uniqid(rand(), TRUE)); //CSRF protection
     $dialog_url = "https://www.facebook.com/dialog/oauth?client_id=" 
       . $app_id . "&redirect_uri=" . urlencode($my_url) . "&state="
       . $_SESSION['state'];

     echo("<script> top.location.href='" . $dialog_url . "'</script>");
   }

   if($_REQUEST['state'] == $_SESSION['state']) {
     $token_url = "https://graph.facebook.com/oauth/access_token?"
       . "client_id=" . $app_id . "&redirect_uri=" . urlencode($my_url)
       . "&client_secret=" . $app_secret . "&code=" . $code;

     $response = file_get_contents($token_url);
     $params = null;
     parse_str($response, $params);

     $graph_url = "https://graph.facebook.com/me?access_token=" 
       . $params['access_token'];

     $user = json_decode(file_get_contents($graph_url));
     echo("Hello " . $user->name);
   }
   else {
     echo("The state does not match. You may be a victim of CSRF.");
   }

 ?>

Solution

  • The first block of code is for retrieving Facebook cookie parameters for users who are already authorized and logged in.

    The second block of code is for letting the user authorize your application (oauth) AND for retrieving an access_token your application can use to make API (FB Graph) calls on the user's behalf.

    $_REQUEST relates to POST or GET parameters, not cookies. If you check the docs on authentication flow, you can see that Facebook redirects the user to http://your_redirect_uri?code=1234abcd after the user has approved your application. You're supposed to grab that code parameter and use it to make another call to graph.facebook.com to get the user's access_token.

    The purpose of session_start() is to prepare the $_SESSION array, so that $_SESSION['state'] is preserved across page reload. If your framework already has session handling code, you can omit it. It's only used for the CSRF protection bit.

    Optional login is pretty straightforward. If you're using the new PHP SDK, you can check the return value of $facebook->getUser(); -- if it's 0, the user is not logged in (and you can show content as normal, with perhaps an additional link to fb_server_side_flow.php to begin the authorization procedure.)