primo commit
This commit is contained in:
571
libraries/vendor/joomla/oauth1/src/Client.php
vendored
Normal file
571
libraries/vendor/joomla/oauth1/src/Client.php
vendored
Normal file
@ -0,0 +1,571 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework OAuth1 Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\OAuth1;
|
||||
|
||||
use Joomla\Application\SessionAwareWebApplicationInterface;
|
||||
use Joomla\Http\Http;
|
||||
use Joomla\Http\HttpFactory;
|
||||
use Joomla\Input\Input;
|
||||
use Joomla\Uri\Uri;
|
||||
|
||||
/**
|
||||
* Joomla Framework class for interacting with an OAuth 1.0 and 1.0a server.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
abstract class Client
|
||||
{
|
||||
/**
|
||||
* Options for the Client object.
|
||||
*
|
||||
* @var array|\ArrayAccess
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $options;
|
||||
|
||||
/**
|
||||
* Contains access token key, secret and verifier.
|
||||
*
|
||||
* @var array
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $token = [];
|
||||
|
||||
/**
|
||||
* The HTTP client object to use in sending HTTP requests.
|
||||
*
|
||||
* @var Http
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* The input object to use in retrieving GET/POST data.
|
||||
*
|
||||
* @var Input
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $input;
|
||||
|
||||
/**
|
||||
* The application object to send HTTP headers for redirects.
|
||||
*
|
||||
* @var SessionAwareWebApplicationInterface
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $application;
|
||||
|
||||
/**
|
||||
* Selects which version of OAuth to use: 1.0 or 1.0a.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $version;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param SessionAwareWebApplicationInterface $application The application object
|
||||
* @param ?Http $client The HTTP client object.
|
||||
* @param ?Input $input The input object
|
||||
* @param array|\ArrayAccess $options OAuth1 Client options.
|
||||
* @param string $version Specify the OAuth version. By default we are using 1.0a.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function __construct(
|
||||
SessionAwareWebApplicationInterface $application,
|
||||
Http $client = null,
|
||||
Input $input = null,
|
||||
$options = [],
|
||||
$version = '1.0a'
|
||||
) {
|
||||
if (!\is_array($options) && !($options instanceof \ArrayAccess)) {
|
||||
throw new \InvalidArgumentException(
|
||||
'The options param must be an array or implement the ArrayAccess interface.'
|
||||
);
|
||||
}
|
||||
|
||||
$this->application = $application;
|
||||
$this->client = $client ?: (new HttpFactory())->getHttp($options);
|
||||
$this->input = $input ?: $application->getInput();
|
||||
$this->options = $options;
|
||||
$this->version = $version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to form the oauth flow.
|
||||
*
|
||||
* @return array|null The access token.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \DomainException
|
||||
*/
|
||||
public function authenticate()
|
||||
{
|
||||
// Already got some credentials stored?
|
||||
if ($this->token) {
|
||||
$response = $this->verifyCredentials();
|
||||
|
||||
if ($response) {
|
||||
return $this->token;
|
||||
}
|
||||
|
||||
$this->token = null;
|
||||
}
|
||||
|
||||
// Check for callback.
|
||||
if (strcmp($this->version, '1.0a') === 0) {
|
||||
$verifier = $this->input->get('oauth_verifier');
|
||||
} else {
|
||||
$verifier = $this->input->get('oauth_token');
|
||||
}
|
||||
|
||||
if (!empty($verifier)) {
|
||||
$session = $this->application->getSession();
|
||||
|
||||
// Get token form session.
|
||||
$this->token = [
|
||||
'key' => $session->get('oauth_token.key'),
|
||||
'secret' => $session->get('oauth_token.secret'),
|
||||
];
|
||||
|
||||
// Verify the returned request token.
|
||||
if (strcmp($this->token['key'], $this->input->get('oauth_token')) !== 0) {
|
||||
throw new \DomainException('Bad session!');
|
||||
}
|
||||
|
||||
// Set token verifier for 1.0a.
|
||||
if (strcmp($this->version, '1.0a') === 0) {
|
||||
$this->token['verifier'] = $this->input->get('oauth_verifier');
|
||||
}
|
||||
|
||||
// Generate access token.
|
||||
$this->generateAccessToken();
|
||||
|
||||
// Return the access token.
|
||||
return $this->token;
|
||||
}
|
||||
|
||||
// Generate a request token.
|
||||
$this->generateRequestToken();
|
||||
|
||||
// Authenticate the user and authorise the app.
|
||||
$this->authorise();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to get a request token.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.1.2
|
||||
* @throws \DomainException
|
||||
*/
|
||||
private function generateRequestToken()
|
||||
{
|
||||
$parameters = [];
|
||||
|
||||
// Set the callback URL.
|
||||
if ($this->getOption('callback')) {
|
||||
$parameters['oauth_callback'] = $this->getOption('callback');
|
||||
}
|
||||
|
||||
// Make an OAuth request for the Request Token.
|
||||
$response = $this->oauthRequest($this->getOption('requestTokenURL'), 'POST', $parameters);
|
||||
|
||||
parse_str($response->body, $params);
|
||||
|
||||
if (strcmp($this->version, '1.0a') === 0 && strcmp($params['oauth_callback_confirmed'], 'true') !== 0) {
|
||||
throw new \DomainException('Bad request token!');
|
||||
}
|
||||
|
||||
// Save the request token.
|
||||
$this->token = ['key' => $params['oauth_token'], 'secret' => $params['oauth_token_secret']];
|
||||
|
||||
// Save the request token in session
|
||||
$session = $this->application->getSession();
|
||||
$session->set('oauth_token.key', $this->token['key']);
|
||||
$session->set('oauth_token.secret', $this->token['secret']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to authorise the application.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.1.2
|
||||
*/
|
||||
private function authorise()
|
||||
{
|
||||
$url = $this->getOption('authoriseURL') . '?oauth_token=' . $this->token['key'];
|
||||
|
||||
if ($this->getOption('scope')) {
|
||||
$scope = \is_array($this->getOption('scope')) ? implode(' ', $this->getOption('scope')) : $this->getOption('scope');
|
||||
$url .= '&scope=' . urlencode($scope);
|
||||
}
|
||||
|
||||
if ($this->getOption('sendheaders')) {
|
||||
$this->application->redirect($url);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to get an access token.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.1.2
|
||||
*/
|
||||
private function generateAccessToken()
|
||||
{
|
||||
// Set the parameters.
|
||||
$parameters = [
|
||||
'oauth_token' => $this->token['key'],
|
||||
];
|
||||
|
||||
if (strcmp($this->version, '1.0a') === 0) {
|
||||
$parameters = array_merge($parameters, ['oauth_verifier' => $this->token['verifier']]);
|
||||
}
|
||||
|
||||
// Make an OAuth request for the Access Token.
|
||||
$response = $this->oauthRequest($this->getOption('accessTokenURL'), 'POST', $parameters);
|
||||
|
||||
parse_str($response->body, $params);
|
||||
|
||||
// Save the access token.
|
||||
$this->token = ['key' => $params['oauth_token'], 'secret' => $params['oauth_token_secret']];
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to make an OAuth request.
|
||||
*
|
||||
* @param string $url The request URL.
|
||||
* @param string $method The request method.
|
||||
* @param array $parameters Array containing request parameters.
|
||||
* @param mixed $data The POST request data.
|
||||
* @param array $headers An array of name-value pairs to include in the header of the request
|
||||
*
|
||||
* @return \Joomla\Http\Response
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \DomainException
|
||||
*/
|
||||
public function oauthRequest($url, $method, $parameters, $data = [], $headers = [])
|
||||
{
|
||||
// Set the parameters.
|
||||
$defaults = [
|
||||
'oauth_consumer_key' => $this->getOption('consumer_key'),
|
||||
'oauth_signature_method' => 'HMAC-SHA1',
|
||||
'oauth_version' => '1.0',
|
||||
'oauth_nonce' => $this->generateNonce(),
|
||||
'oauth_timestamp' => time(),
|
||||
];
|
||||
|
||||
$parameters = array_merge($parameters, $defaults);
|
||||
|
||||
// Do not encode multipart parameters. Do not include $data in the signature if $data is not array.
|
||||
if (isset($headers['Content-Type']) && strpos($headers['Content-Type'], 'multipart/form-data') !== false || !\is_array($data)) {
|
||||
$oauthHeaders = $parameters;
|
||||
} else {
|
||||
// Use all parameters for the signature.
|
||||
$oauthHeaders = array_merge($parameters, $data);
|
||||
}
|
||||
|
||||
// Sign the request.
|
||||
$oauthHeaders = $this->signRequest($url, $method, $oauthHeaders);
|
||||
|
||||
// Get parameters for the Authorisation header.
|
||||
if (\is_array($data)) {
|
||||
$oauthHeaders = array_diff_key($oauthHeaders, $data);
|
||||
}
|
||||
|
||||
// Send the request.
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
$url = $this->toUrl($url, $data);
|
||||
$response = $this->client->get($url, ['Authorization' => $this->createHeader($oauthHeaders)]);
|
||||
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
$headers = array_merge($headers, ['Authorization' => $this->createHeader($oauthHeaders)]);
|
||||
$response = $this->client->post($url, $data, $headers);
|
||||
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
$headers = array_merge($headers, ['Authorization' => $this->createHeader($oauthHeaders)]);
|
||||
$response = $this->client->put($url, $data, $headers);
|
||||
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
$headers = array_merge($headers, ['Authorization' => $this->createHeader($oauthHeaders)]);
|
||||
$response = $this->client->delete($url, $headers);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Validate the response code.
|
||||
$this->validateResponse($url, $response);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to validate a response.
|
||||
*
|
||||
* @param string $url The request URL.
|
||||
* @param Response $response The response to validate.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \DomainException
|
||||
*/
|
||||
abstract public function validateResponse($url, $response);
|
||||
|
||||
/**
|
||||
* Method used to create the header for the POST request.
|
||||
*
|
||||
* @param array $parameters Array containing request parameters.
|
||||
*
|
||||
* @return string The header.
|
||||
*
|
||||
* @since 1.1.2
|
||||
*/
|
||||
private function createHeader(array $parameters): string
|
||||
{
|
||||
$header = 'OAuth ';
|
||||
|
||||
foreach ($parameters as $key => $value) {
|
||||
if (!strcmp($header, 'OAuth ')) {
|
||||
$header .= $key . '="' . $this->safeEncode($value) . '"';
|
||||
} else {
|
||||
$header .= ', ' . $key . '="' . $value . '"';
|
||||
}
|
||||
}
|
||||
|
||||
return $header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to create the URL formed string with the parameters.
|
||||
*
|
||||
* @param string $url The request URL.
|
||||
* @param array $parameters Array containing request parameters.
|
||||
*
|
||||
* @return string The formed URL.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function toUrl($url, $parameters)
|
||||
{
|
||||
$uri = new Uri($url);
|
||||
$uri->setQuery($parameters);
|
||||
|
||||
return (string) $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to sign requests.
|
||||
*
|
||||
* @param string $url The URL to sign.
|
||||
* @param string $method The request method.
|
||||
* @param array $parameters Array containing request parameters.
|
||||
*
|
||||
* @return array The array containing the request parameters, including signature.
|
||||
*
|
||||
* @since 1.1.2
|
||||
*/
|
||||
private function signRequest(string $url, string $method, array $parameters): array
|
||||
{
|
||||
// Create the signature base string.
|
||||
$base = $this->baseString($url, $method, $parameters);
|
||||
|
||||
$parameters['oauth_signature'] = $this->safeEncode(
|
||||
base64_encode(
|
||||
hash_hmac('sha1', $base, $this->prepareSigningKey(), true)
|
||||
)
|
||||
);
|
||||
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the signature base string.
|
||||
*
|
||||
* @param string $url The URL to sign.
|
||||
* @param string $method The request method.
|
||||
* @param array $parameters Array containing request parameters.
|
||||
*
|
||||
* @return string The base string.
|
||||
*
|
||||
* @since 1.1.2
|
||||
*/
|
||||
private function baseString(string $url, string $method, array $parameters): string
|
||||
{
|
||||
// Sort the parameters alphabetically
|
||||
uksort($parameters, 'strcmp');
|
||||
$kv = [];
|
||||
|
||||
// Encode parameters.
|
||||
foreach ($parameters as $key => $value) {
|
||||
$key = $this->safeEncode($key);
|
||||
|
||||
if (\is_array($value)) {
|
||||
foreach ($value as $k => $v) {
|
||||
$v = $this->safeEncode($v);
|
||||
$kv[] = "{$key}={$v}";
|
||||
}
|
||||
} else {
|
||||
$value = $this->safeEncode($value);
|
||||
$kv[] = "{$key}={$value}";
|
||||
}
|
||||
}
|
||||
|
||||
// Form the parameter string.
|
||||
$params = implode('&', $kv);
|
||||
|
||||
// Signature base string elements.
|
||||
$base = [
|
||||
$method,
|
||||
$url,
|
||||
$params,
|
||||
];
|
||||
|
||||
// Return the base string.
|
||||
return implode('&', $this->safeEncode($base));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the string or array passed in a way compatible with OAuth.
|
||||
* If an array is passed each array value will will be encoded.
|
||||
*
|
||||
* @param string|string[] $data The scalar or array to encode.
|
||||
*
|
||||
* @return string|string[] $data encoded in a way compatible with OAuth.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function safeEncode($data)
|
||||
{
|
||||
if (\is_array($data)) {
|
||||
return array_map([$this, 'safeEncode'], $data);
|
||||
}
|
||||
|
||||
if (is_scalar($data)) {
|
||||
return str_ireplace(
|
||||
['+', '%7E'],
|
||||
[' ', '~'],
|
||||
rawurlencode($data)
|
||||
);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to generate the current nonce.
|
||||
*
|
||||
* @return string The current nonce.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function generateNonce()
|
||||
{
|
||||
// The md5s look nicer than numbers.
|
||||
return md5(microtime() . random_bytes(16));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the OAuth signing key.
|
||||
*
|
||||
* @return string The prepared signing key.
|
||||
*
|
||||
* @since 1.1.2
|
||||
*/
|
||||
private function prepareSigningKey(): string
|
||||
{
|
||||
return $this->safeEncode($this->getOption('consumer_secret')) . '&' . $this->safeEncode(($this->token) ? $this->token['secret'] : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an HTTP 200 OK response code and a representation of the requesting user if authentication was successful;
|
||||
* returns a 401 status code and an error message if not.
|
||||
*
|
||||
* @return array The decoded JSON response
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
abstract public function verifyCredentials();
|
||||
|
||||
/**
|
||||
* Get an option from the OAuth1 Client instance.
|
||||
*
|
||||
* @param string $key The name of the option to get
|
||||
* @param mixed $default Optional default value if the option does not exist
|
||||
*
|
||||
* @return mixed The option value
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function getOption($key, $default = null)
|
||||
{
|
||||
return $this->options[$key] ?? $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an option for the OAuth1 Client instance.
|
||||
*
|
||||
* @param string $key The name of the option to set
|
||||
* @param mixed $value The option value to set
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function setOption($key, $value)
|
||||
{
|
||||
$this->options[$key] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the oauth token key or secret.
|
||||
*
|
||||
* @return array The oauth token key and secret.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function getToken()
|
||||
{
|
||||
return $this->token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the oauth token.
|
||||
*
|
||||
* @param array $token The access token key and secret.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function setToken($token)
|
||||
{
|
||||
$this->token = $token;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user