Skip to content
This repository has been archived by the owner on Jan 13, 2022. It is now read-only.

Commit

Permalink
Adding support for the JS cookie and its use in the PHP SDK
Browse files Browse the repository at this point in the history
  • Loading branch information
Jerry Cain authored and Jerry Cain committed Aug 5, 2011
1 parent afa1534 commit 08bf82c
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 12 deletions.
5 changes: 5 additions & 0 deletions readme.md
Expand Up @@ -70,3 +70,8 @@ We are including this in the open source repository to assure you of our
commitment to quality, but also with the hopes that you will contribute back to
help keep it stable. The easiest way to do so is to file bugs and include a
test case.

The tests can be executed by using this command from the base directory:

phpunit --stderr --bootstrap tests/bootstrap.php tests/tests.php

32 changes: 28 additions & 4 deletions src/base_facebook.php
Expand Up @@ -120,7 +120,7 @@ abstract class BaseFacebook
/**
* Version.
*/
const VERSION = '3.0.1';
const VERSION = '3.1.0';

/**
* Default options for curl.
Expand All @@ -129,7 +129,7 @@ abstract class BaseFacebook
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_USERAGENT => 'facebook-php-3.0',
CURLOPT_USERAGENT => 'facebook-php-3.1',
);

/**
Expand Down Expand Up @@ -372,15 +372,19 @@ protected function getUserAccessToken() {
}

/**
* Get the data from a signed_request token.
* Retrieve the signed request, either from a request parameter or,
* if not present, from a cookie.
*
* @return string The base domain
* @return string the signed request, if available, or null otherwise.
*/
public function getSignedRequest() {
if (!$this->signedRequest) {
if (isset($_REQUEST['signed_request'])) {
$this->signedRequest = $this->parseSignedRequest(
$_REQUEST['signed_request']);
} else if (isset($_COOKIE[$this->getSignedRequestCookieName()])) {
$this->signedRequest = $this->parseSignedRequest(
$_COOKIE[$this->getSignedRequestCookieName()]);
}
}
return $this->signedRequest;
Expand Down Expand Up @@ -461,6 +465,13 @@ protected function getUserFromAvailableData() {
public function getLoginUrl($params=array()) {
$this->establishCSRFTokenState();
$currentUrl = $this->getCurrentUrl();

// if 'scope' is passed as an array, convert to comma separated list
$scopeParams = isset($params['scope']) ? $params['scope'] : null;
if ($scopeParams && is_array($scopeParams)) {
$params['scope'] = implode(',', $scopeParams);
}

return $this->getUrl(
'www',
'dialog/oauth',
Expand Down Expand Up @@ -530,6 +541,19 @@ public function api(/* polymorphic */) {
}
}

/**
* Constructs and returns the name of the cookie that
* potentially houses the signed request for the app user.
* The cookie is not set by the BaseFacebook class, but
* it may be set by the JavaScript SDK.
*
* @return string the name of the cookie that would house
* the signed request value.
*/
protected function getSignedRequestCookieName() {
return 'fbsr_'.$this->getAppId();
}

/**
* Get the authorization code from the query parameters, if it exists,
* and otherwise return false to signal no authorization code was
Expand Down
95 changes: 87 additions & 8 deletions tests/tests.php
Expand Up @@ -25,6 +25,7 @@ class PHPSDKTestCase extends PHPUnit_Framework_TestCase {
private static $kExpiredAccessToken = '206492729383450|2.N4RKywNPuHAey7CK56_wmg__.3600.1304560800.1-214707|6Q14AfpYi_XJB26aRQumouzJiGA';
private static $kValidSignedRequest = '1sxR88U4SW9m6QnSxwCEw_CObqsllXhnpP5j2pxD97c.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEyODEwNTI4MDAsIm9hdXRoX3Rva2VuIjoiMTE3NzQzOTcxNjA4MTIwfDIuVlNUUWpub3hYVVNYd1RzcDB1U2g5d19fLjg2NDAwLjEyODEwNTI4MDAtMTY3Nzg0NjM4NXx4NURORHBtcy1nMUM0dUJHQVYzSVdRX2pYV0kuIiwidXNlcl9pZCI6IjE2Nzc4NDYzODUifQ';
private static $kNonTosedSignedRequest = 'c0Ih6vYvauDwncv0n0pndr0hP0mvZaJPQDPt6Z43O0k.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiJ9';
private static $kSignedRequestWithBogusSignature = '1sxR32U4SW9m6QnSxwCEw_CObqsllXhnpP5j2pxD97c.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEyODEwNTI4MDAsIm9hdXRoX3Rva2VuIjoiMTE3NzQzOTcxNjA4MTIwfDIuVlNUUWpub3hYVVNYd1RzcDB1U2g5d19fLjg2NDAwLjEyODEwNTI4MDAtMTY3Nzg0NjM4NXx4NURORHBtcy1nMUM0dUJHQVYzSVdRX2pYV0kuIiwidXNlcl9pZCI6IjE2Nzc4NDYzODUifQ';

public function testConstructor() {
$facebook = new TransientFacebook(array(
Expand Down Expand Up @@ -183,6 +184,39 @@ public function testGetLoginURLWithExtraParams() {
$this->assertEquals(strlen($query_map['state']), $num_characters = 32);
}

public function testGetLoginURLWithScopeParamsAsArray() {
$facebook = new Facebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));

// fake the HPHP $_SERVER globals
$_SERVER['HTTP_HOST'] = 'www.test.com';
$_SERVER['REQUEST_URI'] = '/unit-tests.php';
$scope_params_as_array = array('email','sms','read_stream');
$extra_params = array('scope' => $scope_params_as_array,
'nonsense' => 'nonsense');
$login_url = parse_url($facebook->getLoginUrl($extra_params));
$this->assertEquals($login_url['scheme'], 'https');
$this->assertEquals($login_url['host'], 'www.facebook.com');
$this->assertEquals($login_url['path'], '/dialog/oauth');
// expect api to flatten array params to comma separated list
// should do the same here before asserting to make sure API is behaving
// correctly;
$extra_params['scope'] = implode(',', $scope_params_as_array);
$expected_login_params =
array_merge(
array('client_id' => self::APP_ID,
'redirect_uri' => 'http://www.test.com/unit-tests.php'),
$extra_params);
$query_map = array();
parse_str($login_url['query'], $query_map);
$this->assertIsSubset($expected_login_params, $query_map);
// we don't know what the state is, but we know it's an md5 and should
// be 32 characters long.
$this->assertEquals(strlen($query_map['state']), $num_characters = 32);
}

public function testGetCodeWithValidCSRFState() {
$facebook = new FBCode(array(
'appId' => self::APP_ID,
Expand Down Expand Up @@ -234,6 +268,30 @@ public function testGetUserFromSignedRequest() {
'Failed to get user ID from a valid signed request.');
}

public function testGetSignedRequestFromCookie() {
$facebook = new FBGetSignedRequestCookieFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));

$_COOKIE[$facebook->publicGetSignedRequestCookieName()] =
self::$kValidSignedRequest;
$this->assertNotNull($facebook->publicGetSignedRequest());
$this->assertEquals('1677846385', $facebook->getUser(),
'Failed to get user ID from a valid signed request.');
}

public function testGetSignedRequestWithIncorrectSignature() {
$facebook = new FBGetSignedRequestCookieFacebook(array(
'appId' => self::APP_ID,
'secret' => self::SECRET,
));

$_COOKIE[$facebook->publicGetSignedRequestCookieName()] =
self::$kSignedRequestWithBogusSignature;
$this->assertNull($facebook->publicGetSignedRequest());
}

public function testNonUserAccessToken() {
$facebook = new FBAccessToken(array(
'appId' => self::APP_ID,
Expand Down Expand Up @@ -350,7 +408,7 @@ public function testGraphAPIMethod() {
} catch(FacebookApiException $e) {
// ProfileDelete means the server understood the DELETE
$msg =
'OAuthException: An access token is required to request this resource.';
'OAuthException: A user access token is required to request this resource.';
$this->assertEquals($msg, (string) $e,
'Expect the invalid session message.');
}
Expand Down Expand Up @@ -426,13 +484,24 @@ public function testGraphAPIWithOnlyParams() {
'secret' => self::SECRET,
));

$response = $facebook->api('/331218348435/feed',
array('limit' => 1, 'access_token' => ''));
$this->assertEquals(1, count($response['data']), 'should get one entry');
$this->assertTrue(
strpos($response['paging']['next'], 'limit=1') !== false,
'expect the same limit back in the paging urls'
);
$response = $facebook->api('/jerry');
$this->assertTrue(isset($response['id']),
'User ID should be public.');
$this->assertTrue(isset($response['name']),
'User\'s name should be public.');
$this->assertTrue(isset($response['first_name']),
'User\'s first name should be public.');
$this->assertTrue(isset($response['last_name']),
'User\'s last name should be public.');
$this->assertFalse(isset($response['work']),
'User\'s work history should only be available with '.
'a valid access token.');
$this->assertFalse(isset($response['education']),
'User\'s education history should only be '.
'available with a valid access token.');
$this->assertFalse(isset($response['verified']),
'User\'s verification status should only be '.
'available with a valid access token.');
}

public function testLoginURLDefaults() {
Expand Down Expand Up @@ -839,3 +908,13 @@ public function publicGetCurrentUrl() {
return $this->getCurrentUrl();
}
}

class FBGetSignedRequestCookieFacebook extends TransientFacebook {
public function publicGetSignedRequest() {
return $this->getSignedRequest();
}

public function publicGetSignedRequestCookieName() {
return $this->getSignedRequestCookieName();
}
}

0 comments on commit 08bf82c

Please sign in to comment.