Decoupled access token handling #129

Merged
merged 1 commit into from Jun 25, 2014

Projects

None yet

3 participants

@SammyK
Collaborator
SammyK commented Jun 24, 2014

This continues #95 but will be improved with #36 and #103.

Access tokens have been decoupled from FacebookSession! Yay. Now we can handle access tokens directly.

use Facebook\Entities\AccessToken;

$accessToken = new AccessToken('my_short_lived_token');

// AccessToken object can be echo'ed as a string
echo $accessToken; // my_short_lived_token

// And exchanged for a long lived token
$longLivedToken = $accessToken->extend();

// . . .

// Obtain a code for this long lived token
$code = AccessToken::getCodeFromAccessToken($longLivedToken);
// Obtain a short-lived token for use on clients
$shortLivedAccessTokenForClients = AccessToken::getAccessTokenFromCode($code);

And you can grab it from FacebookSession and play with it.

use Facebook\FacebookRedirectLoginHelper;

$helper = new FacebookRedirectLoginHelper($redirect_url);
$session = $helper->getSessionFromRedirect();

$accessToken = $session->getAccessToken();

if ($accessToken->isLongLived()) {
  // This is a long lived access token.
  // That means you can get a code with it.
  // Or store it in the database and use later.
}

if ($accessToken->expiresAt()) {
  echo 'Your token expires at ' . $accessToken->expiresAt()->format('Y-m-d H:i:s');
} else {
  echo 'Your token never expires!';
}

FacebookSession::getToken() works the same as it always has (returns a string of the access token).

Now, there is still a lot of work to do on this. There are still some pretty deep method calling as well a too much direct access to Graph in the tests, but it's def a good step in the right direction! :)

@yguedidi yguedidi commented on an outdated diff Jun 25, 2014
src/Facebook/Entities/AccessToken.php
+ *
+ * @param int $timeStamp
+ */
+ protected function setExpiresAtFromTimeStamp($timeStamp)
+ {
+ $dt = new \DateTime();
+ $dt->setTimestamp($timeStamp);
+ $this->expiresAt = $dt;
+ }
+
+ /**
+ * Getter for expiresAt.
+ *
+ * @return \DateTime|null
+ */
+ public function expiresAt()
@yguedidi
yguedidi Jun 25, 2014 Collaborator

Should be getExpiresAt(), like in GraphSessionInfo

@yguedidi yguedidi commented on an outdated diff Jun 25, 2014
src/Facebook/Entities/AccessToken.php
+ /**
+ * Getter for expiresAt.
+ *
+ * @return \DateTime|null
+ */
+ public function expiresAt()
+ {
+ return $this->expiresAt;
+ }
+
+ /**
+ * Getter for machineId.
+ *
+ * @return string|null
+ */
+ public function machineId()
@yguedidi
yguedidi Jun 25, 2014 Collaborator

getMachineId() ? :)

@yguedidi yguedidi commented on an outdated diff Jun 25, 2014
src/Facebook/Entities/AccessToken.php
+ *
+ * @return string|null
+ */
+ public function machineId()
+ {
+ return $this->machineId;
+ }
+
+ /**
+ * Determines whether or not this is a long-lived token.
+ *
+ * @return bool
+ */
+ public function isLongLived()
+ {
+ return $this->expiresAt->getTimestamp() > time() + (60 * 2);
@yguedidi
yguedidi Jun 25, 2014 Collaborator

I think you mean time() + (60 * 60 * 2)

@yguedidi yguedidi commented on an outdated diff Jun 25, 2014
src/Facebook/Entities/AccessToken.php
+
+ return static::requestAccessToken($params, $appId, $appSecret);
+ }
+
+ /**
+ * Get a valid code from an access token.
+ *
+ * @param AccessToken|string $accessToken
+ * @param string|null $appId
+ * @param string|null $appSecret
+ *
+ * @return AccessToken
+ */
+ public static function getCodeFromAccessToken($accessToken, $appId = null, $appSecret = null)
+ {
+ $accessToken = $accessToken instanceof AccessToken ? (string) $accessToken : $accessToken;
@yguedidi
yguedidi Jun 25, 2014 Collaborator

Ternery statement not needed, just (string) $accessToken

@yguedidi yguedidi and 1 other commented on an outdated diff Jun 25, 2014
src/Facebook/Entities/AccessToken.php
+ * Request an access token based on a set of params.
+ *
+ * @param array $params
+ * @param string|null $appId
+ * @param string|null $appSecret
+ *
+ * @return AccessToken
+ *
+ * @throws FacebookRequestException
+ */
+ public static function requestAccessToken(array $params, $appId = null, $appSecret = null)
+ {
+ $response = static::request('/oauth/access_token', $params, $appId, $appSecret);
+ $data = $response->getResponse();
+
+ // @TODO fix this malarkey - getResponse() should always return an object
@yguedidi
yguedidi Jun 25, 2014 Collaborator

This should be fixed before merging...

@SammyK
SammyK Jun 25, 2014 Collaborator

This is actually a reference to #36, so it'll be fixed with the next big PR. :)

@yguedidi yguedidi commented on an outdated diff Jun 25, 2014
src/Facebook/Entities/AccessToken.php
+ * @param string|null $appSecret
+ *
+ * @return AccessToken
+ *
+ * @throws FacebookRequestException
+ */
+ public static function requestAccessToken(array $params, $appId = null, $appSecret = null)
+ {
+ $response = static::request('/oauth/access_token', $params, $appId, $appSecret);
+ $data = $response->getResponse();
+
+ // @TODO fix this malarkey - getResponse() should always return an object
+ if (is_array($data)) {
+ if (isset($data['access_token'])) {
+ $expiresAt = isset($data['expires']) ? time() + $data['expires'] : 0;
+ $machineId = isset($data['machine_id']) ? $data['machine_id'] : null;
@yguedidi
yguedidi Jun 25, 2014 Collaborator

No machine_id when $data is an array (from doc, "Exchanging code for an access token")

@yguedidi yguedidi commented on an outdated diff Jun 25, 2014
src/Facebook/Entities/AccessToken.php
+ */
+ public function getInfo($appId = null, $appSecret = null)
+ {
+ $params = array('input_token' => $this->accessToken);
+
+ $request = new FacebookRequest(
+ FacebookSession::newAppSession($appId, $appSecret),
+ 'GET',
+ '/debug_token',
+ $params
+ );
+ $response = $request->execute()->getGraphObject(GraphSessionInfo::className());
+
+ // Update the data on this token
+ if ($response->getExpiresAt())
+ {
@yguedidi
yguedidi Jun 25, 2014 Collaborator

Coding style ;)

@yguedidi yguedidi commented on an outdated diff Jun 25, 2014
src/Facebook/FacebookSession.php
@@ -272,7 +238,10 @@ public static function newSessionFromSignedRequest(SignedRequest $signedRequest)
&& !$signedRequest->get('oauth_token')) {
return self::newSessionAfterValidation($signedRequest);
}
- return new static($signedRequest->get('oauth_token'), $signedRequest);
+ $accessToken = $signedRequest->get('oauth_token');
+ $expiresAt = $signedRequest->get('expires') ?: 0;
@yguedidi
yguedidi Jun 25, 2014 Collaborator

$signedRequest->get('expires', 0) :)

@SammyK
Collaborator
SammyK commented Jun 25, 2014

Thanks for the code review as always @yguedidi! I'll get cracking on these a bit later today. :)

@SammyK
Collaborator
SammyK commented Jun 25, 2014

Done!

@gfosco gfosco merged commit ceb0e69 into facebook:master Jun 25, 2014
@SammyK
Collaborator
SammyK commented Jun 25, 2014

👍 And now to start tackling #36... Phew! :)

@SammyK SammyK deleted the SammyK:decouple-access-token-handling branch Jun 25, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment