Kover as a service ( Formerly on [https://kaas.fun](kaas.fun) )
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
293 lines
8.5 KiB
293 lines
8.5 KiB
9 years ago
|
<?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(),
|
||
|
];
|
||
|
}
|
||
|
}
|