From aed86d2c26ea066cdab31763c1b40591e0aea17d Mon Sep 17 00:00:00 2001 From: Erik Peterson Date: Tue, 19 Nov 2019 19:35:45 +0000 Subject: [PATCH] First pass at oauth 2.0 https://github.com/typhonius/acquia-php-sdk-v2/issues/30 --- composer.json | 4 +- composer.lock | 218 +++++++++++++++++++------------------ src/CloudApi/Connector.php | 40 +++++-- 3 files changed, 143 insertions(+), 119 deletions(-) diff --git a/composer.json b/composer.json index 2f3d64e0..febc8ccc 100644 --- a/composer.json +++ b/composer.json @@ -9,9 +9,9 @@ ], "license": "MIT", "require": { - "acquia/http-hmac-php": "^3.1", "guzzlehttp/guzzle": "^6.3", - "php": ">=5.6" + "php": ">=5.6", + "league/oauth2-client": "^2.4" }, "require-dev": { "php-coveralls/php-coveralls": "^2.0.0", diff --git a/composer.lock b/composer.lock index 3f315bdf..ee20dee3 100644 --- a/composer.lock +++ b/composer.lock @@ -1,74 +1,11 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5d2a00a11b5bb7ea52562f35068690e9", + "content-hash": "6bc1b72f0acef84fd5639a52d3e4d0b4", "packages": [ - { - "name": "acquia/http-hmac-php", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/acquia/http-hmac-php.git", - "reference": "24355c027425ee8e844ae87ac8748a77e6d05c2b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/acquia/http-hmac-php/zipball/24355c027425ee8e844ae87ac8748a77e6d05c2b", - "reference": "24355c027425ee8e844ae87ac8748a77e6d05c2b", - "shasum": "" - }, - "require": { - "php": ">=5.5.0", - "psr/http-message": "~1.0.0", - "sarciszewski/php-future": "~0.4.2" - }, - "replace": { - "acquia/hmac-request": "self.version" - }, - "require-dev": { - "guzzlehttp/guzzle": "~6.0", - "pdepend/pdepend": "~1.0", - "phploc/phploc": "~2.0", - "phpmd/phpmd": "~1.0", - "phpunit/phpunit": "~3.0", - "scrutinizer/ocular": "~1.0", - "sebastian/phpcpd": "~2.0", - "silex/silex": "~1.3.0", - "squizlabs/php_codesniffer": "^2.3", - "symfony/psr-http-message-bridge": "~0.1.0", - "symfony/security": "~3.0.0", - "zendframework/zend-diactoros": "~1.3.5" - }, - "suggest": { - "guzzlehttp/guzzle": "~6.0", - "silex/silex": "~1.3.0", - "symfony/psr-http-message-bridge": "~0.1.0", - "symfony/security": "~3.0.0", - "zendframework/zend-diactoros": "~1.3.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Acquia\\Hmac\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "See contributors", - "homepage": "https://github.com/acquia/http-hmac-php/graphs/contributors" - } - ], - "description": "An implementation of the HTTP HMAC Spec in PHP that integrates with popular libraries such as Symfony and Guzzle.", - "homepage": "https://github.com/acquia/http-hmac-php", - "time": "2017-12-05T17:55:18+00:00" - }, { "name": "guzzlehttp/guzzle", "version": "6.3.0", @@ -251,31 +188,40 @@ "time": "2017-03-20T17:10:46+00:00" }, { - "name": "psr/http-message", - "version": "1.0.1", + "name": "league/oauth2-client", + "version": "2.4.1", "source": { "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + "url": "https://github.com/thephpleague/oauth2-client.git", + "reference": "cc114abc622a53af969e8664722e84ca36257530" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "url": "https://api.github.com/repos/thephpleague/oauth2-client/zipball/cc114abc622a53af969e8664722e84ca36257530", + "reference": "cc114abc622a53af969e8664722e84ca36257530", "shasum": "" }, "require": { - "php": ">=5.3.0" + "guzzlehttp/guzzle": "^6.0", + "paragonie/random_compat": "^1|^2|^9.99", + "php": "^5.6|^7.0" + }, + "require-dev": { + "eloquent/liberator": "^2.0", + "eloquent/phony-phpunit": "^1.0|^3.0", + "jakub-onderka/php-parallel-lint": "^0.9.2", + "phpunit/phpunit": "^5.7|^6.0", + "squizlabs/php_codesniffer": "^2.3|^3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-2.x": "2.0.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Http\\Message\\": "src/" + "League\\OAuth2\\Client\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -284,44 +230,102 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Alex Bilbie", + "email": "hello@alexbilbie.com", + "homepage": "http://www.alexbilbie.com", + "role": "Developer" + }, + { + "name": "Woody Gilk", + "homepage": "https://github.com/shadowhand", + "role": "Contributor" } ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", + "description": "OAuth 2.0 Client Library", "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "time": "2016-08-06T14:39:51+00:00" + "Authentication", + "SSO", + "authorization", + "identity", + "idp", + "oauth", + "oauth2", + "single sign on" + ], + "time": "2018-11-22T18:33:57+00:00" }, { - "name": "sarciszewski/php-future", - "version": "0.4.2", + "name": "paragonie/random_compat", + "version": "v9.99.99", "source": { "type": "git", - "url": "https://github.com/sarciszewski/php-future.git", - "reference": "8bcc414eecfe68bb4600ab9b179ef6e8454b8ca0" + "url": "https://github.com/paragonie/random_compat.git", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sarciszewski/php-future/zipball/8bcc414eecfe68bb4600ab9b179ef6e8454b8ca0", - "reference": "8bcc414eecfe68bb4600ab9b179ef6e8454b8ca0", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", "shasum": "" }, + "require": { + "php": "^7" + }, "require-dev": { - "phpunit/phpunit": "4.5.*" + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "time": "2018-07-02T15:55:56+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { - "files": [ - "autoload.php" - ] + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -329,20 +333,21 @@ ], "authors": [ { - "name": "Scott Arciszewski", - "email": "scott@paragonie.com", - "homepage": "https://appsec.solutions", - "role": "Developer" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "Polyfill new (5.6+) features into old (5.4+) versions of PHP", + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", "keywords": [ - "compatibility", - "future", - "hash_equals", - "security" + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" ], - "time": "2015-09-28T20:04:00+00:00" + "time": "2016-08-06T14:39:51+00:00" } ], "packages-dev": [ @@ -1235,6 +1240,7 @@ "mock", "xunit" ], + "abandoned": true, "time": "2017-12-10T08:01:53+00:00" }, { diff --git a/src/CloudApi/Connector.php b/src/CloudApi/Connector.php index 5e98dfcb..f24f4d2f 100644 --- a/src/CloudApi/Connector.php +++ b/src/CloudApi/Connector.php @@ -2,13 +2,12 @@ namespace AcquiaCloudApi\CloudApi; -use Acquia\Hmac\Guzzle\HmacAuthMiddleware; -use Acquia\Hmac\Key; +use League\OAuth2\Client\Provider\GenericProvider; +use League\OAuth2\Client\Provider\Exception\IdentityProviderException; use GuzzleHttp\Client as GuzzleClient; use GuzzleHttp\Exception\ClientException; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; -use GuzzleHttp\HandlerStack; /** * Class Connector @@ -21,6 +20,16 @@ class Connector implements ConnectorInterface */ const BASE_URI = 'https://cloud.acquia.com/api'; + /** + * @var GenericProvider The OAuth 2.0 provider to use in communication. + */ + protected $provider; + + /** + * @var string The generated OAuth 2.0 access token. + */ + protected $accessToken; + /** * @var GuzzleClient The Guzzle Client to communicate with the API. */ @@ -38,13 +47,12 @@ class Connector implements ConnectorInterface */ public function __construct($config) { - $key = new Key($config['key'], $config['secret']); - $middleware = new HmacAuthMiddleware($key); - $stack = HandlerStack::create(); - $stack->push($middleware); - - $this->client = new GuzzleClient([ - 'handler' => $stack, + $this->provider = new GenericProvider([ + 'clientId' => $config['key'], + 'clientSecret' => $config['secret'], + 'urlAuthorize' => '', + 'urlAccessToken' => 'https://accounts.acquia.com/api/auth/oauth/token', + 'urlResourceOwnerDetails' => '', ]); } @@ -82,8 +90,18 @@ public function request(string $verb, string $path, array $query = [], array $op */ public function makeRequest(string $verb, string $path, array $query = [], array $options = []) { + if (! isset($this->accessToken)) { + $this->accessToken = $this->provider->getAccessToken('client_credentials'); + } + try { - $response = $this->client->$verb(self::BASE_URI . $path, $options); + $request = $this->provider->getAuthenticatedRequest( + $verb, + self::BASE_URI . $path, + $this->accessToken + ); + $client = new GuzzleClient(); + $response = $client->send($request, $options); } catch (ClientException $e) { print $e->getMessage(); $response = $e->getResponse();