From 205b8477f22efe8f6272ed4e7eeee4d23490c3da Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 6 Apr 2018 09:39:34 +0200 Subject: [PATCH 01/14] composer: switching OAuth implementation. --- composer.json | 6 +- composer.lock | 533 +++++++++++++++++++++++++++++++++++++------------- 2 files changed, 403 insertions(+), 136 deletions(-) diff --git a/composer.json b/composer.json index 4515289..33cbb8e 100644 --- a/composer.json +++ b/composer.json @@ -1,8 +1,8 @@ { "require": { "robmorgan/phinx": "^0.9.2", - "opauth/google": "^0.2.2", - "opauth/twitter": "^0.3.1", - "opauth/github": "^0.1.0" + "league/oauth2-client": "^2.3", + "league/oauth2-github": "^2.0", + "league/oauth2-google": "^2.2" } } diff --git a/composer.lock b/composer.lock index 711d59a..341ad08 100644 --- a/composer.lock +++ b/composer.lock @@ -4,123 +4,106 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "36a75ff648970b9639580a2cb7013090", - "content-hash": "ac20c7c56c417cb600cb228332de7513", + "hash": "e15241d12e55005941680fd13b7adfd5", + "content-hash": "6a1223c65b159915526ef261e5adfbea", "packages": [ { - "name": "opauth/github", - "version": "0.1.0", + "name": "guzzlehttp/guzzle", + "version": "6.3.2", "source": { "type": "git", - "url": "https://github.com/opauth/github.git", - "reference": "9c4fe16dc6498b2c94f4c2a41ab93b0fe4b7fa73" + "url": "https://github.com/guzzle/guzzle.git", + "reference": "68d0ea14d5a3f42a20e87632a5f84931e2709c90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opauth/github/zipball/9c4fe16dc6498b2c94f4c2a41ab93b0fe4b7fa73", - "reference": "9c4fe16dc6498b2c94f4c2a41ab93b0fe4b7fa73", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/68d0ea14d5a3f42a20e87632a5f84931e2709c90", + "reference": "68d0ea14d5a3f42a20e87632a5f84931e2709c90", "shasum": "" }, "require": { - "opauth/opauth": ">=0.4.0", - "php": ">=5.2.0" + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.4", + "php": ">=5.5" }, - "type": "library", - "autoload": { - "psr-0": { - "": "." - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "U-Zyn Chua", - "email": "chua@uzyn.com", - "homepage": "http://uzyn.com" - } - ], - "description": "GitHub authentication strategy for Opauth", - "homepage": "http://opauth.org", - "keywords": [ - "Authentication", - "auth", - "github" - ], - "time": "2012-07-23 06:13:59" - }, - { - "name": "opauth/google", - "version": "0.2.2", - "source": { - "type": "git", - "url": "https://github.com/opauth/google.git", - "reference": "35df77684c14acb346a8c3753ae3809852d1a47e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/opauth/google/zipball/35df77684c14acb346a8c3753ae3809852d1a47e", - "reference": "35df77684c14acb346a8c3753ae3809852d1a47e", - "shasum": "" - }, - "require": { - "opauth/opauth": ">=0.2.0", - "php": ">=5.2.0" - }, - "type": "library", - "autoload": { - "psr-0": { - "": "." - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "U-Zyn Chua", - "email": "chua@uzyn.com", - "homepage": "http://uzyn.com" - } - ], - "description": "Google strategy for Opauth", - "homepage": "http://opauth.org", - "keywords": [ - "Authentication", - "auth", - "google" - ], - "time": "2012-10-18 14:39:52" - }, - { - "name": "opauth/opauth", - "version": "0.4.5", - "source": { - "type": "git", - "url": "https://github.com/opauth/opauth.git", - "reference": "3f979012d0bdf2d447bb02b97f7f7d9f482c77e8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/opauth/opauth/zipball/3f979012d0bdf2d447bb02b97f7f7d9f482c77e8", - "reference": "3f979012d0bdf2d447bb02b97f7f7d9f482c77e8", - "shasum": "" - }, - "require": { - "php": ">=5.2.0" + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4", + "psr/log": "^1.0" }, "suggest": { - "opauth/facebook": "Allows Facebook authentication", - "opauth/google": "Allows Google authentication", - "opauth/twitter": "Allows Twitter authentication" + "psr/log": "Required for using the Log middleware" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.3-dev" + } + }, "autoload": { - "classmap": [ - "lib/Opauth/" + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2018-03-26 16:33:04" + }, + { + "name": "guzzlehttp/promises", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -129,47 +112,117 @@ ], "authors": [ { - "name": "U-Zyn Chua", - "email": "chua@uzyn.com", - "homepage": "http://uzyn.com" + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" } ], - "description": "Multi-provider authentication framework for PHP", - "homepage": "http://opauth.org", + "description": "Guzzle promises library", "keywords": [ - "Authentication", - "OpenId", - "auth", - "facebook", - "google", - "oauth", - "omniauth", - "twitter" + "promise" ], - "time": "2018-02-25 03:18:21" + "time": "2016-12-20 10:07:11" }, { - "name": "opauth/twitter", - "version": "0.3.2", + "name": "guzzlehttp/psr7", + "version": "1.4.2", "source": { "type": "git", - "url": "https://github.com/opauth/twitter.git", - "reference": "9c09fb3d714b8bf7b35ebc235346cf2feced69e3" + "url": "https://github.com/guzzle/psr7.git", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opauth/twitter/zipball/9c09fb3d714b8bf7b35ebc235346cf2feced69e3", - "reference": "9c09fb3d714b8bf7b35ebc235346cf2feced69e3", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", "shasum": "" }, "require": { - "opauth/opauth": ">=0.2.0", - "php": ">=5.2.0" + "php": ">=5.4.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, "autoload": { - "psr-0": { - "": "." + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "request", + "response", + "stream", + "uri", + "url" + ], + "time": "2017-03-20 17:10:46" + }, + { + "name": "league/oauth2-client", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/oauth2-client.git", + "reference": "aa2e3df188f0bfd87f7880cc880e906e99923580" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/oauth2-client/zipball/aa2e3df188f0bfd87f7880cc880e906e99923580", + "reference": "aa2e3df188f0bfd87f7880cc880e906e99923580", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.0", + "paragonie/random_compat": "^1|^2", + "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-2.x": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\OAuth2\\Client\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -178,19 +231,233 @@ ], "authors": [ { - "name": "U-Zyn Chua", - "email": "chua@uzyn.com", - "homepage": "http://uzyn.com" + "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": "Twitter strategy for Opauth", - "homepage": "http://opauth.org", + "description": "OAuth 2.0 Client Library", "keywords": [ "Authentication", - "auth", - "twitter" + "SSO", + "authorization", + "identity", + "idp", + "oauth", + "oauth2", + "single sign on" ], - "time": "2017-03-28 05:03:36" + "time": "2018-01-13 05:27:58" + }, + { + "name": "league/oauth2-github", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/oauth2-github.git", + "reference": "e63d64f3ec167c09232d189c6b0c397458a99357" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/oauth2-github/zipball/e63d64f3ec167c09232d189c6b0c397458a99357", + "reference": "e63d64f3ec167c09232d189c6b0c397458a99357", + "shasum": "" + }, + "require": { + "league/oauth2-client": "^2.0" + }, + "require-dev": { + "mockery/mockery": "~0.9", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\OAuth2\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Steven Maguire", + "email": "stevenmaguire@gmail.com", + "homepage": "https://github.com/stevenmaguire" + } + ], + "description": "Github OAuth 2.0 Client Provider for The PHP League OAuth2-Client", + "keywords": [ + "authorisation", + "authorization", + "client", + "github", + "oauth", + "oauth2" + ], + "time": "2017-01-26 01:14:51" + }, + { + "name": "league/oauth2-google", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/oauth2-google.git", + "reference": "c0faed29ec6d665ce3234e01f62029516cee4c02" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/oauth2-google/zipball/c0faed29ec6d665ce3234e01f62029516cee4c02", + "reference": "c0faed29ec6d665ce3234e01f62029516cee4c02", + "shasum": "" + }, + "require": { + "league/oauth2-client": "^2.0" + }, + "require-dev": { + "eloquent/phony": "^0.14.6", + "phpunit/phpunit": "^5.7", + "satooshi/php-coveralls": "^2.0", + "squizlabs/php_codesniffer": "^2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\OAuth2\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Woody Gilk", + "email": "woody.gilk@gmail.com", + "homepage": "http://shadowhand.me" + } + ], + "description": "Google OAuth 2.0 Client Provider for The PHP League OAuth2-Client", + "keywords": [ + "Authentication", + "authorization", + "client", + "google", + "oauth", + "oauth2" + ], + "time": "2018-03-19 17:28:55" + }, + { + "name": "paragonie/random_compat", + "version": "v2.0.12", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/258c89a6b97de7dfaf5b8c7607d0478e236b04fb", + "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "autoload": { + "files": [ + "lib/random.php" + ] + }, + "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", + "pseudorandom", + "random" + ], + "time": "2018-04-04 21:24:14" + }, + { + "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": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2016-08-06 14:39:51" }, { "name": "psr/log", From 556a62b34b44f9c89de6d5a0d70a5f6f63b18e05 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 6 Apr 2018 11:36:29 +0200 Subject: [PATCH 02/14] adding app/library/OAuth/Adapter classes (interface and League adapter) --- .../OAuth/Adapter/AdapterInterface.php | 43 +++++++++++ app/library/OAuth/Adapter/League.php | 73 +++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 app/library/OAuth/Adapter/AdapterInterface.php create mode 100644 app/library/OAuth/Adapter/League.php diff --git a/app/library/OAuth/Adapter/AdapterInterface.php b/app/library/OAuth/Adapter/AdapterInterface.php new file mode 100644 index 0000000..676a6f2 --- /dev/null +++ b/app/library/OAuth/Adapter/AdapterInterface.php @@ -0,0 +1,43 @@ +_provider = $provider; + } + + /** + * {@inheritDoc} + */ + public function getProviderName() + { + return (new \ReflectionClass($this->_provider))->getShortName(); + } + + /** + * {@inheritDoc} + */ + public function getAuthorizationUrl() + { + return $this->_provider->getAuthorizationUrl(); + } + + /** + * {@inheritDoc} + */ + public function fetchAccessToken($code) + { + $this->_accessToken = $this->_provider->getAccessToken('authorization_code', [ + 'code' => $code + ]); + } + + /** + * {@inheritDoc} + */ + public function getResourceData() + { + $resource = $this->_provider->getResourceOwner($this->_accessToken); + return $resource->toArray(); + } +} From 21c869a06af8601caa69c58e1633b896a919b2b2 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 6 Apr 2018 11:37:45 +0200 Subject: [PATCH 03/14] adding app/library/OAuth/UserData classes (interface and Github implementation) --- app/library/OAuth/UserData/Github.php | 56 +++++++++++++++++++ .../OAuth/UserData/UserDataInterface.php | 43 ++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 app/library/OAuth/UserData/Github.php create mode 100644 app/library/OAuth/UserData/UserDataInterface.php diff --git a/app/library/OAuth/UserData/Github.php b/app/library/OAuth/UserData/Github.php new file mode 100644 index 0000000..d8b4d13 --- /dev/null +++ b/app/library/OAuth/UserData/Github.php @@ -0,0 +1,56 @@ +data = $data; + } + + /** + * {@inheritDoc} + */ + public function getProvider() + { + return 'Github'; + } + + /** + * {@inheritDoc} + */ + public function getId() + { + return (int) $this->data['id']; + } + + /** + * {@inheritDoc} + */ + public function getUsername() + { + return $this->data['login']; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return $this->data['name']; + } + + /** + * {@inheritDoc} + */ + public function getEmail() + { + return $this->data['email']; + } +} diff --git a/app/library/OAuth/UserData/UserDataInterface.php b/app/library/OAuth/UserData/UserDataInterface.php new file mode 100644 index 0000000..cf489a3 --- /dev/null +++ b/app/library/OAuth/UserData/UserDataInterface.php @@ -0,0 +1,43 @@ + Date: Fri, 6 Apr 2018 11:39:13 +0200 Subject: [PATCH 04/14] rename app/library/OAuth.php to app/library/OAuth/Client.php and change implementation to use Adapter classes. --- app/library/OAuth.php | 103 ----------------------------------- app/library/OAuth/Client.php | 59 ++++++++++++++++++++ 2 files changed, 59 insertions(+), 103 deletions(-) delete mode 100644 app/library/OAuth.php create mode 100644 app/library/OAuth/Client.php diff --git a/app/library/OAuth.php b/app/library/OAuth.php deleted file mode 100644 index c08de76..0000000 --- a/app/library/OAuth.php +++ /dev/null @@ -1,103 +0,0 @@ - '/oauth/', - 'callback_url' => '/oauth/callback' - ); - - protected $_oauth; - - protected $_callbackName = 'callback'; - - public function __construct($config) - { - $config = $this->objectToArray($config->oauth); - - $this->_config = array_merge($this->_config, $config); - - $this->_oauth = new Opauth($this->_config, false); - } - - /** - * @return mixed|null|void - */ - public function perform() - { - $strategy = $this->dispatcher->getParam('strategy', null, false); - - if ($strategy == $this->_callbackName) { - return $this->getResponse(); - } - - $this->_oauth->run(); - exit; - } - - /** - * @return array|string - */ - public function getResponse() - { - $response = null; - switch($this->_oauth->env['callback_transport']) { - case 'session': - $response = $this->session->get('opauth'); - $this->session->remove('opauth'); - break; - case 'post': - $response = unserialize(base64_decode( $_POST['opauth'] )); - break; - case 'get': - $response = unserialize(base64_decode( $_GET['opauth'] )); - break; - } - - $ret = $this->_validate($response, $reason); - if ($ret === false) { - return $reason; - } - return $response; - } - - public function objectToArray($object) - { - if(!is_object($object) && !is_array($object)) - { - return $object; - } - if(is_object($object)) - { - $object = get_object_vars( $object ); - } - return array_map(array($this,"objectToArray"), $object ); - } - - protected function _validate($response, &$reason) - { - if (isset($response['auth']) && - isset($response['timestamp']) && - isset($response['signature'])) { - - $hash = sha1(print_r($response['auth'], true)); - - return $this->_oauth->validate($hash, $response['timestamp'], - $response['signature'], $reason); - } - - $reason = "Invalid auth response"; - return false; - } -} diff --git a/app/library/OAuth/Client.php b/app/library/OAuth/Client.php new file mode 100644 index 0000000..be703e8 --- /dev/null +++ b/app/library/OAuth/Client.php @@ -0,0 +1,59 @@ +_adapter = $adapter; + } + + public function getAuthorizationUrl() + { + return $this->_adapter->getAuthorizationUrl(); + } + + /** + * @param string $code + * @return UserDataInterface + */ + public function authenticate($code) + { + $this->_adapter->fetchAccessToken($code); + + return $this->getUserData(); + } + + /** + * @return UserDataInterface + */ + public function getUserData() + { + $data = $this->_adapter->getResourceData(); + return $this->_createUserData($data); + } + + protected function _createUserData(array $data) + { + $name = $this->_adapter->getProviderName(); + $class = "Httpcb\\OAuth\\UserData\\{$name}"; + return new $class($data); + } +} From f966cfb9115439865d6b05dd0a4e26caef327cc9 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 6 Apr 2018 11:40:35 +0200 Subject: [PATCH 05/14] app/config/services.php: setup "oauth" using the new implementation --- app/config/services.php | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/app/config/services.php b/app/config/services.php index 0193e1f..3e12006 100644 --- a/app/config/services.php +++ b/app/config/services.php @@ -24,7 +24,8 @@ use Phalcon\Di\FactoryDefault, Phalcon\Mvc\Router; use Httpcb\Auth, - Httpcb\OAuth, + Httpcb\OAuth\Client as OAuthClient, + Httpcb\OAuth\Adapter\League as OAuthAdapter, Httpcb\Acl, Httpcb\Navigation, Httpcb\Menu; @@ -294,8 +295,18 @@ $di->setShared('flash', function () { return new Phalcon\Flash\Session(); }); -$di->set('oauth', function() use ($config) { - return new OAuth($config); +$di->set('oauth', function($provider) use ($config) { + + if (isset($config->oauth->providers->{$provider})) { + $options = $config->oauth->providers->{$provider}; + $options = $options->toArray(); + } else { + $options = array(); + } + + $adapter = new OAuthAdapter($provider, $options); + + return new OAuthClient($adapter); }); $di->set('auth', function() use ($di, $config) { From adfeb97f1ab97790e31df2522f50c2a4e37ed849 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 6 Apr 2018 11:43:19 +0200 Subject: [PATCH 06/14] app/config/conf.local.sample.yml: update to reflect the new OAuth implementation. --- app/config/conf.local.sample.yml | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/app/config/conf.local.sample.yml b/app/config/conf.local.sample.yml index f365936..8fa5619 100644 --- a/app/config/conf.local.sample.yml +++ b/app/config/conf.local.sample.yml @@ -13,13 +13,7 @@ database: # OAuth #oauth: - #security_salt: value - #debug: 1 - - #Strategy: - # Google: - # client_id: value - # client_secret: value - # GitHub: - # client_id: value - # client_secret: value + #providers: + #github: + #clientId: value + #clientSecret: value From ef8e78084e7e5a544bb81c6ace717662c8277385 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 6 Apr 2018 11:48:01 +0200 Subject: [PATCH 07/14] app/controllers/AuthController.php: in oauthAction() use the new implementation of OAuth. --- app/controllers/AuthController.php | 31 ++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/app/controllers/AuthController.php b/app/controllers/AuthController.php index bc4edae..b3a84ba 100644 --- a/app/controllers/AuthController.php +++ b/app/controllers/AuthController.php @@ -40,16 +40,31 @@ class AuthController extends ControllerBase $this->view->form = $form; } - public function oauthAction() + public function oauthAction($provider_name) { - $response = $this->oauth->perform(); + $client = $this->getDI()->get('oauth', [ $provider_name ]); - if (is_array($response)) { - $this->auth->loginOauth($response['auth']); - $this->response->redirect('/'); - } else { - $this->flash->message('error', 'Failed to authenticate.'); - $this->response->redirect('/login'); + $code = $this->request->get('code'); + $state = $this->request->get('state'); + + // Have code. Authenticate and fetch data. + if (strlen($code) > 0) { + + try { + // NOTE: Should pass $state here also. + $data = $client->authenticate($code); + + $this->auth->loginOauth($data); + $this->response->redirect('/'); + } catch(\Exception $e) { + $this->flash->message('error', 'Failed to authenticate.'); + $this->response->redirect('/login'); + } + } + // No code + else { + // redirect to provider and acquire code. + $this->response->redirect($client->getAuthorizationUrl(), true); } } From deed1c531814172b769940914e3fc11918e2a845 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 6 Apr 2018 11:48:36 +0200 Subject: [PATCH 08/14] app/library/Auth.php: in loginOAuth() we pass a UserDataInterface now. --- app/library/Auth.php | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/app/library/Auth.php b/app/library/Auth.php index 0aa51b5..e6e2333 100644 --- a/app/library/Auth.php +++ b/app/library/Auth.php @@ -2,6 +2,7 @@ namespace Httpcb; +use Httpcb\OAuth\UserData\UserDataInterface; use Phalcon\Mvc\User\Component; use App\Model\Data\User; @@ -42,24 +43,19 @@ class Auth extends Component /** * Login using OAuth * - * @param $auth + * @param UserDataInterface $auth */ - public function loginOauth($auth) + public function loginOauth(UserDataInterface $auth) { - $email = ''; - if (isset($auth['info']['email'])) { - $email = $auth['info']['email']; - } - // Look for a user with this email. - $user = User::findFirstByEmail($email); + $user = User::findFirstByEmail($auth->getEmail()); if (!$user) { // Did not find any user. create him. - if (isset($auth['info']['nickname'])) { - $name = $auth['info']['nickname']; - } else if(isset($auth['info']['name'])) { - $name = $auth['info']['name']; + if (strlen($auth->getUsername()) > 0) { + $name = $auth->getUsername(); + } else if(strlen($auth->getName()) > 0) { + $name = $auth->getName(); } else { $name = ''; } @@ -74,7 +70,7 @@ class Auth extends Component $this->setIdentity($user->getId()); $this->_eventsManager->fire('auth:onLogin', $this, - "OAuth {$auth['provider']}"); + "OAuth {$auth->getProvider()}"); } /** From 52ea0c753161e166d1e8ffc62e5060a2cd679878 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 6 Apr 2018 11:50:07 +0200 Subject: [PATCH 09/14] app/config/services.php: in router, change /oauth/{strategy} to /login/{strategy} for oauth route. --- app/config/services.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/config/services.php b/app/config/services.php index 3e12006..34d1fab 100644 --- a/app/config/services.php +++ b/app/config/services.php @@ -121,7 +121,7 @@ $di->setShared('router', function() { 'action' => 'logout', ))->setName('logout'); - $router->add('/oauth/{strategy:([a-z]+)}/:params', array( + $router->add('/login/{strategy:([a-z]+)}/:params', array( 'controller' => 'auth', 'action' => 'oauth' ))->setName('oauth'); From 158cacdb8a81e76138e3ba5ed59b44ed1743fdc7 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 9 Apr 2018 00:06:10 +0200 Subject: [PATCH 10/14] composer: adding omines/oauth2-gitlab --- composer.json | 3 ++- composer.lock | 65 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 33cbb8e..27c26ec 100644 --- a/composer.json +++ b/composer.json @@ -3,6 +3,7 @@ "robmorgan/phinx": "^0.9.2", "league/oauth2-client": "^2.3", "league/oauth2-github": "^2.0", - "league/oauth2-google": "^2.2" + "league/oauth2-google": "^2.2", + "omines/oauth2-gitlab": "^3.1" } } diff --git a/composer.lock b/composer.lock index 341ad08..c412c31 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "e15241d12e55005941680fd13b7adfd5", - "content-hash": "6a1223c65b159915526ef261e5adfbea", + "hash": "7d98cc9a7b6f4f79576273e599f7b1f4", + "content-hash": "0fd142e805b37679388bfea151fd3970", "packages": [ { "name": "guzzlehttp/guzzle", @@ -361,6 +361,67 @@ ], "time": "2018-03-19 17:28:55" }, + { + "name": "omines/oauth2-gitlab", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/omines/oauth2-gitlab.git", + "reference": "e9cf370897b42edeffc6946123a1bd22d6006c33" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/omines/oauth2-gitlab/zipball/e9cf370897b42edeffc6946123a1bd22d6006c33", + "reference": "e9cf370897b42edeffc6946123a1bd22d6006c33", + "shasum": "" + }, + "require": { + "league/oauth2-client": "^2.2", + "php": ">=5.6" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.0", + "m4tthumphrey/php-gitlab-api": "^9.0.0", + "mockery/mockery": "^1.0", + "php-http/guzzle6-adapter": "^1.1.1", + "phpunit/phpunit": "^5.7 || ^6.0" + }, + "suggest": { + "m4tthumphrey/php-gitlab-api": "For further API usage using the acquired OAuth2 token" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Omines\\OAuth2\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Niels Keurentjes", + "email": "niels.keurentjes@omines.com", + "homepage": "https://www.omines.nl/" + } + ], + "description": "GitLab OAuth 2.0 Client Provider for The PHP League OAuth2-Client", + "keywords": [ + "authorisation", + "authorization", + "client", + "gitlab", + "oauth", + "oauth2" + ], + "time": "2017-11-01 21:46:33" + }, { "name": "paragonie/random_compat", "version": "v2.0.12", From 4042b36422c1db708039f195a7529b04afd8c785 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 9 Apr 2018 00:06:57 +0200 Subject: [PATCH 11/14] app/library/OAuth/Adapter/League.php: add support for non-standard providers. --- app/library/OAuth/Adapter/League.php | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/app/library/OAuth/Adapter/League.php b/app/library/OAuth/Adapter/League.php index d1ebeb6..cf85b14 100644 --- a/app/library/OAuth/Adapter/League.php +++ b/app/library/OAuth/Adapter/League.php @@ -7,6 +7,16 @@ use League\OAuth2\Client\Provider\AbstractProvider, class League implements AdapterInterface { + /** + * List of all supported providers and their class name. + * + * @var array + */ + protected $_providerClasses = array( + 'github' => '\League\OAuth2\Client\Provider\Github', + 'gitlab' => '\Omines\OAuth2\Client\Provider\Gitlab', + ); + /** * @var AbstractProvider */ @@ -17,15 +27,19 @@ class League implements AdapterInterface */ protected $_accessToken; + protected $_options; + /** * {@inheritDoc} * @throws Exception */ public function __construct($provider_name, $options) { - $provider_name = ucfirst($provider_name); + if (!array_key_exists($provider_name, $this->_providerClasses)) { + throw new Exception("Provider '{$provider_name}' is not supported."); + } - $className = 'League\OAuth2\Client\Provider\\' . $provider_name; + $className = $this->_providerClasses[$provider_name]; $provider = new $className($options); if (!($provider instanceof AbstractProvider)) { @@ -34,6 +48,7 @@ class League implements AdapterInterface } $this->_provider = $provider; + $this->_options = $options; } /** @@ -49,7 +64,7 @@ class League implements AdapterInterface */ public function getAuthorizationUrl() { - return $this->_provider->getAuthorizationUrl(); + return $this->_provider->getAuthorizationUrl($this->_options); } /** From e62a93e0216f93a58d203d88741628268d79c395 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 9 Apr 2018 00:07:11 +0200 Subject: [PATCH 12/14] adding app/library/OAuth/UserData/Gitlab.php --- app/library/OAuth/UserData/Gitlab.php | 56 +++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 app/library/OAuth/UserData/Gitlab.php diff --git a/app/library/OAuth/UserData/Gitlab.php b/app/library/OAuth/UserData/Gitlab.php new file mode 100644 index 0000000..697747a --- /dev/null +++ b/app/library/OAuth/UserData/Gitlab.php @@ -0,0 +1,56 @@ +data = $data; + } + + /** + * {@inheritDoc} + */ + public function getProvider() + { + return 'Gitlab'; + } + + /** + * {@inheritDoc} + */ + public function getId() + { + return (int) $this->data['id']; + } + + /** + * {@inheritDoc} + */ + public function getUsername() + { + return $this->data['username']; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return $this->data['name']; + } + + /** + * {@inheritDoc} + */ + public function getEmail() + { + return $this->data['email']; + } +} From ab8ebbc0934943400d5989fc703da2dde77a448a Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 9 Apr 2018 00:52:17 +0200 Subject: [PATCH 13/14] less: adding the gitlab button --- app/assets/less/components/button.less | 1 + app/assets/less/variables.less | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/app/assets/less/components/button.less b/app/assets/less/components/button.less index 488399f..3c57b37 100644 --- a/app/assets/less/components/button.less +++ b/app/assets/less/components/button.less @@ -46,6 +46,7 @@ .button-light { .button-variant(@text-light-color, @button-bg-color, @button-hover-color); } .button-github { .button-variant(@button-github-color, @button-github-bg); } +.button-gitlab { .button-variant(@button-gitlab-color, @button-gitlab-bg); } .button-google { .button-variant(@button-google-color, @button-google-bg); } // Outline diff --git a/app/assets/less/variables.less b/app/assets/less/variables.less index ad716d8..fb7f240 100644 --- a/app/assets/less/variables.less +++ b/app/assets/less/variables.less @@ -31,6 +31,7 @@ @brand-info: hsl(210, 70%, 50%); @google-color: #db4437; @github-color: #4183c4; +@gitlab-color: #548; // ---------------------------------- // Font @@ -112,6 +113,9 @@ @button-github-bg: @github-color; @button-github-border: darken(@button-github-bg, 5%); +@button-gitlab-color: white; +@button-gitlab-bg: @gitlab-color; + // ---------------------------------- // Shadows // ---------------------------------- From ee58c343e76be5dc760a9810cecf9d1cc410f11a Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Mon, 9 Apr 2018 00:52:40 +0200 Subject: [PATCH 14/14] app/views/auth/index.volt: adding a gitlab button. --- app/views/auth/index.volt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/views/auth/index.volt b/app/views/auth/index.volt index 90f8a71..491d2c6 100644 --- a/app/views/auth/index.volt +++ b/app/views/auth/index.volt @@ -37,6 +37,10 @@ {{ icon('social-google') }} Google + + + Gitlab +