summaryrefslogtreecommitdiff
path: root/lib/facebook-graph-sdk/src/Facebook/Authentication
diff options
context:
space:
mode:
Diffstat (limited to 'lib/facebook-graph-sdk/src/Facebook/Authentication')
-rw-r--r--lib/facebook-graph-sdk/src/Facebook/Authentication/AccessToken.php160
-rw-r--r--lib/facebook-graph-sdk/src/Facebook/Authentication/AccessTokenMetadata.php390
-rw-r--r--lib/facebook-graph-sdk/src/Facebook/Authentication/OAuth2Client.php292
3 files changed, 842 insertions, 0 deletions
diff --git a/lib/facebook-graph-sdk/src/Facebook/Authentication/AccessToken.php b/lib/facebook-graph-sdk/src/Facebook/Authentication/AccessToken.php
new file mode 100644
index 0000000..582ea61
--- /dev/null
+++ b/lib/facebook-graph-sdk/src/Facebook/Authentication/AccessToken.php
@@ -0,0 +1,160 @@
+<?php
+/**
+ * Copyright 2014 Facebook, Inc.
+ *
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
+ * use, copy, modify, and distribute this software in source code or binary
+ * form for use in connection with the web services and APIs provided by
+ * Facebook.
+ *
+ * As with any software that integrates with the Facebook platform, your use
+ * of this software is subject to the Facebook Developer Principles and
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
+ * shall be included in all copies or substantial portions of the software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+namespace Facebook\Authentication;
+
+/**
+ * Class AccessToken
+ *
+ * @package Facebook
+ */
+class AccessToken
+{
+ /**
+ * The access token value.
+ *
+ * @var string
+ */
+ protected $value = '';
+
+ /**
+ * Date when token expires.
+ *
+ * @var \DateTime|null
+ */
+ protected $expiresAt;
+
+ /**
+ * Create a new access token entity.
+ *
+ * @param string $accessToken
+ * @param int $expiresAt
+ */
+ public function __construct($accessToken, $expiresAt = 0)
+ {
+ $this->value = $accessToken;
+ if ($expiresAt) {
+ $this->setExpiresAtFromTimeStamp($expiresAt);
+ }
+ }
+
+ /**
+ * Generate an app secret proof to sign a request to Graph.
+ *
+ * @param string $appSecret The app secret.
+ *
+ * @return string
+ */
+ public function getAppSecretProof($appSecret)
+ {
+ return hash_hmac('sha256', $this->value, $appSecret);
+ }
+
+ /**
+ * Getter for expiresAt.
+ *
+ * @return \DateTime|null
+ */
+ public function getExpiresAt()
+ {
+ return $this->expiresAt;
+ }
+
+ /**
+ * Determines whether or not this is an app access token.
+ *
+ * @return bool
+ */
+ public function isAppAccessToken()
+ {
+ return strpos($this->value, '|') !== false;
+ }
+
+ /**
+ * Determines whether or not this is a long-lived token.
+ *
+ * @return bool
+ */
+ public function isLongLived()
+ {
+ if ($this->expiresAt) {
+ return $this->expiresAt->getTimestamp() > time() + (60 * 60 * 2);
+ }
+
+ if ($this->isAppAccessToken()) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks the expiration of the access token.
+ *
+ * @return boolean|null
+ */
+ public function isExpired()
+ {
+ if ($this->getExpiresAt() instanceof \DateTime) {
+ return $this->getExpiresAt()->getTimestamp() < time();
+ }
+
+ if ($this->isAppAccessToken()) {
+ return false;
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the access token as a string.
+ *
+ * @return string
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ /**
+ * Returns the access token as a string.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->getValue();
+ }
+
+ /**
+ * Setter for expires_at.
+ *
+ * @param int $timeStamp
+ */
+ protected function setExpiresAtFromTimeStamp($timeStamp)
+ {
+ $dt = new \DateTime();
+ $dt->setTimestamp($timeStamp);
+ $this->expiresAt = $dt;
+ }
+}
diff --git a/lib/facebook-graph-sdk/src/Facebook/Authentication/AccessTokenMetadata.php b/lib/facebook-graph-sdk/src/Facebook/Authentication/AccessTokenMetadata.php
new file mode 100644
index 0000000..f302a6d
--- /dev/null
+++ b/lib/facebook-graph-sdk/src/Facebook/Authentication/AccessTokenMetadata.php
@@ -0,0 +1,390 @@
+<?php
+/**
+ * Copyright 2014 Facebook, Inc.
+ *
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
+ * use, copy, modify, and distribute this software in source code or binary
+ * form for use in connection with the web services and APIs provided by
+ * Facebook.
+ *
+ * As with any software that integrates with the Facebook platform, your use
+ * of this software is subject to the Facebook Developer Principles and
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
+ * shall be included in all copies or substantial portions of the software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+namespace Facebook\Authentication;
+
+use Facebook\Exceptions\FacebookSDKException;
+
+/**
+ * Class AccessTokenMetadata
+ *
+ * Represents metadata from an access token.
+ *
+ * @package Facebook
+ * @see https://developers.facebook.com/docs/graph-api/reference/debug_token
+ */
+class AccessTokenMetadata
+{
+ /**
+ * The access token metadata.
+ *
+ * @var array
+ */
+ protected $metadata = [];
+
+ /**
+ * Properties that should be cast as DateTime objects.
+ *
+ * @var array
+ */
+ protected static $dateProperties = ['expires_at', 'issued_at'];
+
+ /**
+ * @param array $metadata
+ *
+ * @throws FacebookSDKException
+ */
+ public function __construct(array $metadata)
+ {
+ if (!isset($metadata['data'])) {
+ throw new FacebookSDKException('Unexpected debug token response data.', 401);
+ }
+
+ $this->metadata = $metadata['data'];
+
+ $this->castTimestampsToDateTime();
+ }
+
+ /**
+ * Returns a value from the metadata.
+ *
+ * @param string $field The property to retrieve.
+ * @param mixed $default The default to return if the property doesn't exist.
+ *
+ * @return mixed
+ */
+ public function getField($field, $default = null)
+ {
+ if (isset($this->metadata[$field])) {
+ return $this->metadata[$field];
+ }
+
+ return $default;
+ }
+
+ /**
+ * Returns a value from the metadata.
+ *
+ * @param string $field The property to retrieve.
+ * @param mixed $default The default to return if the property doesn't exist.
+ *
+ * @return mixed
+ *
+ * @deprecated 5.0.0 getProperty() has been renamed to getField()
+ * @todo v6: Remove this method
+ */
+ public function getProperty($field, $default = null)
+ {
+ return $this->getField($field, $default);
+ }
+
+ /**
+ * Returns a value from a child property in the metadata.
+ *
+ * @param string $parentField The parent property.
+ * @param string $field The property to retrieve.
+ * @param mixed $default The default to return if the property doesn't exist.
+ *
+ * @return mixed
+ */
+ public function getChildProperty($parentField, $field, $default = null)
+ {
+ if (!isset($this->metadata[$parentField])) {
+ return $default;
+ }
+
+ if (!isset($this->metadata[$parentField][$field])) {
+ return $default;
+ }
+
+ return $this->metadata[$parentField][$field];
+ }
+
+ /**
+ * Returns a value from the error metadata.
+ *
+ * @param string $field The property to retrieve.
+ * @param mixed $default The default to return if the property doesn't exist.
+ *
+ * @return mixed
+ */
+ public function getErrorProperty($field, $default = null)
+ {
+ return $this->getChildProperty('error', $field, $default);
+ }
+
+ /**
+ * Returns a value from the "metadata" metadata. *Brain explodes*
+ *
+ * @param string $field The property to retrieve.
+ * @param mixed $default The default to return if the property doesn't exist.
+ *
+ * @return mixed
+ */
+ public function getMetadataProperty($field, $default = null)
+ {
+ return $this->getChildProperty('metadata', $field, $default);
+ }
+
+ /**
+ * The ID of the application this access token is for.
+ *
+ * @return string|null
+ */
+ public function getAppId()
+ {
+ return $this->getField('app_id');
+ }
+
+ /**
+ * Name of the application this access token is for.
+ *
+ * @return string|null
+ */
+ public function getApplication()
+ {
+ return $this->getField('application');
+ }
+
+ /**
+ * Any error that a request to the graph api
+ * would return due to the access token.
+ *
+ * @return bool|null
+ */
+ public function isError()
+ {
+ return $this->getField('error') !== null;
+ }
+
+ /**
+ * The error code for the error.
+ *
+ * @return int|null
+ */
+ public function getErrorCode()
+ {
+ return $this->getErrorProperty('code');
+ }
+
+ /**
+ * The error message for the error.
+ *
+ * @return string|null
+ */
+ public function getErrorMessage()
+ {
+ return $this->getErrorProperty('message');
+ }
+
+ /**
+ * The error subcode for the error.
+ *
+ * @return int|null
+ */
+ public function getErrorSubcode()
+ {
+ return $this->getErrorProperty('subcode');
+ }
+
+ /**
+ * DateTime when this access token expires.
+ *
+ * @return \DateTime|null
+ */
+ public function getExpiresAt()
+ {
+ return $this->getField('expires_at');
+ }
+
+ /**
+ * Whether the access token is still valid or not.
+ *
+ * @return boolean|null
+ */
+ public function getIsValid()
+ {
+ return $this->getField('is_valid');
+ }
+
+ /**
+ * DateTime when this access token was issued.
+ *
+ * Note that the issued_at field is not returned
+ * for short-lived access tokens.
+ *
+ * @see https://developers.facebook.com/docs/facebook-login/access-tokens#debug
+ *
+ * @return \DateTime|null
+ */
+ public function getIssuedAt()
+ {
+ return $this->getField('issued_at');
+ }
+
+ /**
+ * General metadata associated with the access token.
+ * Can contain data like 'sso', 'auth_type', 'auth_nonce'.
+ *
+ * @return array|null
+ */
+ public function getMetadata()
+ {
+ return $this->getField('metadata');
+ }
+
+ /**
+ * The 'sso' child property from the 'metadata' parent property.
+ *
+ * @return string|null
+ */
+ public function getSso()
+ {
+ return $this->getMetadataProperty('sso');
+ }
+
+ /**
+ * The 'auth_type' child property from the 'metadata' parent property.
+ *
+ * @return string|null
+ */
+ public function getAuthType()
+ {
+ return $this->getMetadataProperty('auth_type');
+ }
+
+ /**
+ * The 'auth_nonce' child property from the 'metadata' parent property.
+ *
+ * @return string|null
+ */
+ public function getAuthNonce()
+ {
+ return $this->getMetadataProperty('auth_nonce');
+ }
+
+ /**
+ * For impersonated access tokens, the ID of
+ * the page this token contains.
+ *
+ * @return string|null
+ */
+ public function getProfileId()
+ {
+ return $this->getField('profile_id');
+ }
+
+ /**
+ * List of permissions that the user has granted for
+ * the app in this access token.
+ *
+ * @return array
+ */
+ public function getScopes()
+ {
+ return $this->getField('scopes');
+ }
+
+ /**
+ * The ID of the user this access token is for.
+ *
+ * @return string|null
+ */
+ public function getUserId()
+ {
+ return $this->getField('user_id');
+ }
+
+ /**
+ * Ensures the app ID from the access token
+ * metadata is what we expect.
+ *
+ * @param string $appId
+ *
+ * @throws FacebookSDKException
+ */
+ public function validateAppId($appId)
+ {
+ if ($this->getAppId() !== $appId) {
+ throw new FacebookSDKException('Access token metadata contains unexpected app ID.', 401);
+ }
+ }
+
+ /**
+ * Ensures the user ID from the access token
+ * metadata is what we expect.
+ *
+ * @param string $userId
+ *
+ * @throws FacebookSDKException
+ */
+ public function validateUserId($userId)
+ {
+ if ($this->getUserId() !== $userId) {
+ throw new FacebookSDKException('Access token metadata contains unexpected user ID.', 401);
+ }
+ }
+
+ /**
+ * Ensures the access token has not expired yet.
+ *
+ * @throws FacebookSDKException
+ */
+ public function validateExpiration()
+ {
+ if (!$this->getExpiresAt() instanceof \DateTime) {
+ return;
+ }
+
+ if ($this->getExpiresAt()->getTimestamp() < time()) {
+ throw new FacebookSDKException('Inspection of access token metadata shows that the access token has expired.', 401);
+ }
+ }
+
+ /**
+ * Converts a unix timestamp into a DateTime entity.
+ *
+ * @param int $timestamp
+ *
+ * @return \DateTime
+ */
+ private function convertTimestampToDateTime($timestamp)
+ {
+ $dt = new \DateTime();
+ $dt->setTimestamp($timestamp);
+
+ return $dt;
+ }
+
+ /**
+ * Casts the unix timestamps as DateTime entities.
+ */
+ private function castTimestampsToDateTime()
+ {
+ foreach (static::$dateProperties as $key) {
+ if (isset($this->metadata[$key])) {
+ $this->metadata[$key] = $this->convertTimestampToDateTime($this->metadata[$key]);
+ }
+ }
+ }
+}
diff --git a/lib/facebook-graph-sdk/src/Facebook/Authentication/OAuth2Client.php b/lib/facebook-graph-sdk/src/Facebook/Authentication/OAuth2Client.php
new file mode 100644
index 0000000..8e364ec
--- /dev/null
+++ b/lib/facebook-graph-sdk/src/Facebook/Authentication/OAuth2Client.php
@@ -0,0 +1,292 @@
+<?php
+/**
+ * Copyright 2014 Facebook, Inc.
+ *
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
+ * use, copy, modify, and distribute this software in source code or binary
+ * form for use in connection with the web services and APIs provided by
+ * Facebook.
+ *
+ * As with any software that integrates with the Facebook platform, your use
+ * of this software is subject to the Facebook Developer Principles and
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
+ * shall be included in all copies or substantial portions of the software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+namespace Facebook\Authentication;
+
+use Facebook\Facebook;
+use Facebook\FacebookApp;
+use Facebook\FacebookRequest;
+use Facebook\FacebookResponse;
+use Facebook\FacebookClient;
+use Facebook\Exceptions\FacebookResponseException;
+use Facebook\Exceptions\FacebookSDKException;
+
+/**
+ * Class OAuth2Client
+ *
+ * @package Facebook
+ */
+class OAuth2Client
+{
+ /**
+ * @const string The base authorization URL.
+ */
+ const BASE_AUTHORIZATION_URL = 'https://www.facebook.com';
+
+ /**
+ * The FacebookApp entity.
+ *
+ * @var FacebookApp
+ */
+ protected $app;
+
+ /**
+ * The Facebook client.
+ *
+ * @var FacebookClient
+ */
+ protected $client;
+
+ /**
+ * The version of the Graph API to use.
+ *
+ * @var string
+ */
+ protected $graphVersion;
+
+ /**
+ * The last request sent to Graph.
+ *
+ * @var FacebookRequest|null
+ */
+ protected $lastRequest;
+
+ /**
+ * @param FacebookApp $app
+ * @param FacebookClient $client
+ * @param string|null $graphVersion The version of the Graph API to use.
+ */
+ public function __construct(FacebookApp $app, FacebookClient $client, $graphVersion = null)
+ {
+ $this->app = $app;
+ $this->client = $client;
+ $this->graphVersion = $graphVersion ?: Facebook::DEFAULT_GRAPH_VERSION;
+ }
+
+ /**
+ * Returns the last FacebookRequest that was sent.
+ * Useful for debugging and testing.
+ *
+ * @return FacebookRequest|null
+ */
+ public function getLastRequest()
+ {
+ return $this->lastRequest;
+ }
+
+ /**
+ * Get the metadata associated with the access token.
+ *
+ * @param AccessToken|string $accessToken The access token to debug.
+ *
+ * @return AccessTokenMetadata
+ */
+ public function debugToken($accessToken)
+ {
+ $accessToken = $accessToken instanceof AccessToken ? $accessToken->getValue() : $accessToken;
+ $params = ['input_token' => $accessToken];
+
+ $this->lastRequest = new FacebookRequest(
+ $this->app,
+ $this->app->getAccessToken(),
+ 'GET',
+ '/debug_token',
+ $params,
+ null,
+ $this->graphVersion
+ );
+ $response = $this->client->sendRequest($this->lastRequest);
+ $metadata = $response->getDecodedBody();
+
+ return new AccessTokenMetadata($metadata);
+ }
+
+ /**
+ * Generates an authorization URL to begin the process of authenticating a user.
+ *
+ * @param string $redirectUrl The callback URL to redirect to.
+ * @param array $scope An array of permissions to request.
+ * @param string $state The CSPRNG-generated CSRF value.
+ * @param array $params An array of parameters to generate URL.
+ * @param string $separator The separator to use in http_build_query().
+ *
+ * @return string
+ */
+ public function getAuthorizationUrl($redirectUrl, $state, array $scope = [], array $params = [], $separator = '&')
+ {
+ $params += [
+ 'client_id' => $this->app->getId(),
+ 'state' => $state,
+ 'response_type' => 'code',
+ 'sdk' => 'php-sdk-' . Facebook::VERSION,
+ 'redirect_uri' => $redirectUrl,
+ 'scope' => implode(',', $scope)
+ ];
+
+ return static::BASE_AUTHORIZATION_URL . '/' . $this->graphVersion . '/dialog/oauth?' . http_build_query($params, null, $separator);
+ }
+
+ /**
+ * Get a valid access token from a code.
+ *
+ * @param string $code
+ * @param string $redirectUri
+ *
+ * @return AccessToken
+ *
+ * @throws FacebookSDKException
+ */
+ public function getAccessTokenFromCode($code, $redirectUri = '')
+ {
+ $params = [
+ 'code' => $code,
+ 'redirect_uri' => $redirectUri,
+ ];
+
+ return $this->requestAnAccessToken($params);
+ }
+
+ /**
+ * Exchanges a short-lived access token with a long-lived access token.
+ *
+ * @param AccessToken|string $accessToken
+ *
+ * @return AccessToken
+ *
+ * @throws FacebookSDKException
+ */
+ public function getLongLivedAccessToken($accessToken)
+ {
+ $accessToken = $accessToken instanceof AccessToken ? $accessToken->getValue() : $accessToken;
+ $params = [
+ 'grant_type' => 'fb_exchange_token',
+ 'fb_exchange_token' => $accessToken,
+ ];
+
+ return $this->requestAnAccessToken($params);
+ }
+
+ /**
+ * Get a valid code from an access token.
+ *
+ * @param AccessToken|string $accessToken
+ * @param string $redirectUri
+ *
+ * @return AccessToken
+ *
+ * @throws FacebookSDKException
+ */
+ public function getCodeFromLongLivedAccessToken($accessToken, $redirectUri = '')
+ {
+ $params = [
+ 'redirect_uri' => $redirectUri,
+ ];
+
+ $response = $this->sendRequestWithClientParams('/oauth/client_code', $params, $accessToken);
+ $data = $response->getDecodedBody();
+
+ if (!isset($data['code'])) {
+ throw new FacebookSDKException('Code was not returned from Graph.', 401);
+ }
+
+ return $data['code'];
+ }
+
+ /**
+ * Send a request to the OAuth endpoint.
+ *
+ * @param array $params
+ *
+ * @return AccessToken
+ *
+ * @throws FacebookSDKException
+ */
+ protected function requestAnAccessToken(array $params)
+ {
+ $response = $this->sendRequestWithClientParams('/oauth/access_token', $params);
+ $data = $response->getDecodedBody();
+
+ if (!isset($data['access_token'])) {
+ throw new FacebookSDKException('Access token was not returned from Graph.', 401);
+ }
+
+ // Graph returns two different key names for expiration time
+ // on the same endpoint. Doh! :/
+ $expiresAt = 0;
+ if (isset($data['expires'])) {
+ // For exchanging a short lived token with a long lived token.
+ // The expiration time in seconds will be returned as "expires".
+ $expiresAt = time() + $data['expires'];
+ } elseif (isset($data['expires_in'])) {
+ // For exchanging a code for a short lived access token.
+ // The expiration time in seconds will be returned as "expires_in".
+ // See: https://developers.facebook.com/docs/facebook-login/access-tokens#long-via-code
+ $expiresAt = time() + $data['expires_in'];
+ }
+
+ return new AccessToken($data['access_token'], $expiresAt);
+ }
+
+ /**
+ * Send a request to Graph with an app access token.
+ *
+ * @param string $endpoint
+ * @param array $params
+ * @param string|null $accessToken
+ *
+ * @return FacebookResponse
+ *
+ * @throws FacebookResponseException
+ */
+ protected function sendRequestWithClientParams($endpoint, array $params, $accessToken = null)
+ {
+ $params += $this->getClientParams();
+
+ $accessToken = $accessToken ?: $this->app->getAccessToken();
+
+ $this->lastRequest = new FacebookRequest(
+ $this->app,
+ $accessToken,
+ 'GET',
+ $endpoint,
+ $params,
+ null,
+ $this->graphVersion
+ );
+
+ return $this->client->sendRequest($this->lastRequest);
+ }
+
+ /**
+ * Returns the client_* params for OAuth requests.
+ *
+ * @return array
+ */
+ protected function getClientParams()
+ {
+ return [
+ 'client_id' => $this->app->getId(),
+ 'client_secret' => $this->app->getSecret(),
+ ];
+ }
+}