diff --git a/composer.json b/composer.json index 0a7037c..3638b1f 100644 --- a/composer.json +++ b/composer.json @@ -2,12 +2,6 @@ "name": "edgardmessias/glpi-singlesignon", "description": "", "require": { - "league/oauth2-client": "^2.2", - "league/oauth2-facebook": "^2.0", - "league/oauth2-github": "^2.0", - "league/oauth2-google": "^3.0", - "league/oauth2-instagram": "^2.0", - "league/oauth2-linkedin": "^4.0" }, "require-dev": { "glpi-project/coding-standard": "^0.7.1" diff --git a/composer.lock b/composer.lock index cbb698c..d9bdb83 100644 --- a/composer.lock +++ b/composer.lock @@ -4,699 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0771db2050853a723fe36fe91dbf19ad", - "packages": [ - { - "name": "guzzlehttp/guzzle", - "version": "6.3.3", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", - "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", - "shasum": "" - }, - "require": { - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.4", - "php": ">=5.5" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", - "psr/log": "^1.0" - }, - "suggest": { - "psr/log": "Required for using the Log middleware" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.3-dev" - } - }, - "autoload": { - "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-04-22T15:46:56+00:00" - }, - { - "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/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ], - "time": "2016-12-20T10:07:11+00:00" - }, - { - "name": "guzzlehttp/psr7", - "version": "1.5.2", - "source": { - "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "9f83dded91781a01c63574e387eaa769be769115" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/9f83dded91781a01c63574e387eaa769be769115", - "reference": "9f83dded91781a01c63574e387eaa769be769115", - "shasum": "" - }, - "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0", - "ralouphie/getallheaders": "^2.0.5" - }, - "provide": { - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.5-dev" - } - }, - "autoload": { - "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", - "psr-7", - "request", - "response", - "stream", - "uri", - "url" - ], - "time": "2018-12-04T20:46:45+00:00" - }, - { - "name": "jakeasmith/http_build_url", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/jakeasmith/http_build_url.git", - "reference": "93c273e77cb1edead0cf8bcf8cd2003428e74e37" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/jakeasmith/http_build_url/zipball/93c273e77cb1edead0cf8bcf8cd2003428e74e37", - "reference": "93c273e77cb1edead0cf8bcf8cd2003428e74e37", - "shasum": "" - }, - "type": "library", - "autoload": { - "files": [ - "src/http_build_url.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jake A. Smith", - "email": "theman@jakeasmith.com" - } - ], - "description": "Provides functionality for http_build_url() to environments without pecl_http.", - "time": "2017-05-01T15:36:40+00:00" - }, - { - "name": "league/oauth2-client", - "version": "2.4.1", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/oauth2-client.git", - "reference": "cc114abc622a53af969e8664722e84ca36257530" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth2-client/zipball/cc114abc622a53af969e8664722e84ca36257530", - "reference": "cc114abc622a53af969e8664722e84ca36257530", - "shasum": "" - }, - "require": { - "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-2.x": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "League\\OAuth2\\Client\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "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": "OAuth 2.0 Client Library", - "keywords": [ - "Authentication", - "SSO", - "authorization", - "identity", - "idp", - "oauth", - "oauth2", - "single sign on" - ], - "time": "2018-11-22T18:33:57+00:00" - }, - { - "name": "league/oauth2-facebook", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/oauth2-facebook.git", - "reference": "bcbcd540fb66ae16b4f82671c8ae7752b6a89556" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth2-facebook/zipball/bcbcd540fb66ae16b4f82671c8ae7752b6a89556", - "reference": "bcbcd540fb66ae16b4f82671c8ae7752b6a89556", - "shasum": "" - }, - "require": { - "league/oauth2-client": "^2.0", - "php": "^5.6 || ^7.0" - }, - "require-dev": { - "mockery/mockery": "~0.9", - "phpunit/phpunit": "~4.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": "Sammy Kaye Powers", - "email": "me@sammyk.me", - "homepage": "http://www.sammyk.me" - } - ], - "description": "Facebook OAuth 2.0 Client Provider for The PHP League OAuth2-Client", - "keywords": [ - "Authentication", - "authorization", - "client", - "facebook", - "oauth", - "oauth2" - ], - "time": "2017-07-22T01:25:00+00:00" - }, - { - "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-26T01:14:51+00:00" - }, - { - "name": "league/oauth2-google", - "version": "3.0.1", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/oauth2-google.git", - "reference": "3290273029f7cc2a468aae68bad184479a23b9d2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth2-google/zipball/3290273029f7cc2a468aae68bad184479a23b9d2", - "reference": "3290273029f7cc2a468aae68bad184479a23b9d2", - "shasum": "" - }, - "require": { - "league/oauth2-client": "^2.0" - }, - "require-dev": { - "eloquent/phony-phpunit": "^2.0", - "php-coveralls/php-coveralls": "^2.1", - "phpunit/phpunit": "^6.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-12-28T16:18:33+00:00" - }, - { - "name": "league/oauth2-instagram", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/oauth2-instagram.git", - "reference": "abf6466ebd2c2a73e920b0ce834e2bf50d1abdcc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth2-instagram/zipball/abf6466ebd2c2a73e920b0ce834e2bf50d1abdcc", - "reference": "abf6466ebd2c2a73e920b0ce834e2bf50d1abdcc", - "shasum": "" - }, - "require": { - "jakeasmith/http_build_url": "^1.0", - "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": "Instagram OAuth 2.0 Client Provider for The PHP League OAuth2-Client", - "keywords": [ - "authorisation", - "authorization", - "client", - "instagram", - "oauth", - "oauth2" - ], - "time": "2017-01-26T01:21:29+00:00" - }, - { - "name": "league/oauth2-linkedin", - "version": "4.1.1", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/oauth2-linkedin.git", - "reference": "0dfb338db84cb87c3d24b0205ec7f3e3a9457b81" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth2-linkedin/zipball/0dfb338db84cb87c3d24b0205ec7f3e3a9457b81", - "reference": "0dfb338db84cb87c3d24b0205ec7f3e3a9457b81", - "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": "LinkedIn OAuth 2.0 Client Provider for The PHP League OAuth2-Client", - "keywords": [ - "authorisation", - "authorization", - "client", - "linkedin", - "oauth", - "oauth2" - ], - "time": "2018-07-23T15:43:54+00:00" - }, - { - "name": "paragonie/random_compat", - "version": "v2.0.18", - "source": { - "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "0a58ef6e3146256cc3dc7cc393927bcc7d1b72db" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/0a58ef6e3146256cc3dc7cc393927bcc7d1b72db", - "reference": "0a58ef6e3146256cc3dc7cc393927bcc7d1b72db", - "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", - "polyfill", - "pseudorandom", - "random" - ], - "time": "2019-01-03T20:59:08+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": { - "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-06T14:39:51+00:00" - }, - { - "name": "ralouphie/getallheaders", - "version": "2.0.5", - "source": { - "type": "git", - "url": "https://github.com/ralouphie/getallheaders.git", - "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/5601c8a83fbba7ef674a7369456d12f1e0d0eafa", - "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa", - "shasum": "" - }, - "require": { - "php": ">=5.3" - }, - "require-dev": { - "phpunit/phpunit": "~3.7.0", - "satooshi/php-coveralls": ">=1.0" - }, - "type": "library", - "autoload": { - "files": [ - "src/getallheaders.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ralph Khattar", - "email": "ralph.khattar@gmail.com" - } - ], - "description": "A polyfill for getallheaders.", - "time": "2016-02-11T07:05:27+00:00" - } - ], + "content-hash": "ad5ec11e41165b0453caa49df99ecde3", + "packages": [], "packages-dev": [ { "name": "glpi-project/coding-standard", diff --git a/front/callback.php b/front/callback.php index 61ab1de..5c9a8e7 100644 --- a/front/callback.php +++ b/front/callback.php @@ -1,7 +1,11 @@ prepareProviderInstance(); - $signon_provider->checkAuthorization(); if ($signon_provider->login()) { diff --git a/inc/provider.class.php b/inc/provider.class.php index 7049aae..dfaa4c0 100644 --- a/inc/provider.class.php +++ b/inc/provider.class.php @@ -7,21 +7,25 @@ class PluginSinglesignonProvider extends CommonDBTM { static $rightname = 'config'; /** - * Provider instance - * @var null|\League\OAuth2\Client\Provider\GenericProvider + * @var array + */ + static $default = null; + + /** + * + * @var string */ - protected $_provider = null; protected $_code = null; /** * - * @var null|\League\OAuth2\Client\Token\AccessToken + * @var null|string */ protected $_token = null; /** * - * @var null|\League\OAuth2\Client\Provider\ResourceOwnerInterface + * @var null|array */ protected $_resource_owner = null; @@ -536,56 +540,126 @@ static function processMassiveActionsForOneItemtype(MassiveAction $ma, CommonDBT parent::processMassiveActionsForOneItemtype($ma, $item, $ids); } - /** - * - * @param string $type - * @param array $options - * @param array $collaborators - * @return \League\OAuth2\Client\Provider\AbstractProvider - */ - public static function createInstance($type = 'generic', array $options = [], array $collaborators = []) { - global $CFG_GLPI; + public static function getDefault($type, $key, $default = null) { + if (static::$default === null) { + $content = file_get_contents(dirname(__FILE__) . '/../providers.json'); + static::$default = json_decode($content, true); + } - if (!isset($options['scope'])) { - $options['scope'] = []; + if (isset(static::$default[$type]) && static::$default[$type][$key]) { + return static::$default[$type][$key]; } - $clientOptions = ['verify' => false]; + return $default; + } - if (!empty($CFG_GLPI["proxy_name"])) { - $clientOptions['proxy'] = $CFG_GLPI["proxy_name"] . ":" . $CFG_GLPI["proxy_port"]; + public function getClientType() { + $value = "generic"; - if (!empty($CFG_GLPI["proxy_user"])) { - $clientOptions['proxy'] = $CFG_GLPI["proxy_user"] . ":" . - Toolbox::decrypt($CFG_GLPI["proxy_passwd"], GLPIKEY) . - "@" . $clientOptions['proxy']; - } + if (isset($this->fields['type']) && !empty($this->fields['type'])) { + $value = $this->fields['type']; } - $httpClient = new GuzzleHttp\Client($clientOptions); + return $value; + } - $collaborators['httpClient'] = $httpClient; + public function getClientId() { + $value = ""; - switch ($type) { - case 'facebook': - if (!isset($options['graphApiVersion'])) { - $options['graphApiVersion'] = 'v2.12'; - } - return new League\OAuth2\Client\Provider\Facebook($options, $collaborators); - case 'github': - $options['scope'][] = 'user:email'; - return new League\OAuth2\Client\Provider\Github($options, $collaborators); - case 'google': - return new League\OAuth2\Client\Provider\Google($options, $collaborators); - case 'instagram': - return new League\OAuth2\Client\Provider\Instagram($options, $collaborators); - case 'linkedin': - $options['scope'][] = 'r_emailaddress'; - return new League\OAuth2\Client\Provider\LinkedIn($options, $collaborators); - case 'generic': - default: - return new League\OAuth2\Client\Provider\GenericProvider($options, $collaborators); + if (isset($this->fields['client_id']) && !empty($this->fields['client_id'])) { + $value = $this->fields['client_id']; + } + + return $value; + } + + public function getClientSecret() { + $value = ""; + + if (isset($this->fields['client_secret']) && !empty($this->fields['client_secret'])) { + $value = $this->fields['client_secret']; + } + + return $value; + } + + public function getScope() { + $value = ""; + + $default = [ + 'github' => 'user:email', + 'linkedin' => 'r_emailaddress', + ]; + + $type = $this->getClientType(); + + if (isset($default[$type])) { + $value = $default[$type]; } + + $fields = $this->fields; + + if (!isset($fields['scope']) || empty($fields['scope'])) { + $fields['scope'] = $value; + } + + $fields = Plugin::doHookFunction("sso:scope", $fields); + + return $fields['scope']; + } + + public function getAuthorizeUrl() { + $type = $this->getClientType(); + + $value = static::getDefault($type, "url_authorize"); + + $fields = $this->fields; + + if (!isset($fields['url_authorize']) || empty($fields['url_authorize'])) { + $fields['url_authorize'] = $value; + } + + $fields = Plugin::doHookFunction("sso:url_authorize", $fields); + + return $fields['url_authorize']; + } + + public function getAccessTokenUrl() { + $type = $this->getClientType(); + + $value = static::getDefault($type, "url_access_token"); + + $fields = $this->fields; + + if (!isset($fields['url_access_token']) || empty($fields['url_access_token'])) { + $fields['url_access_token'] = $value; + } + + $fields = Plugin::doHookFunction("sso:url_access_token", $fields); + + return $fields['url_access_token']; + } + + public function getResourceOwnerDetailsUrl($access_token) { + $type = $this->getClientType(); + + $value = static::getDefault($type, "url_resource_owner_details", ""); + + $fields = $this->fields; + $fields['access_token'] = $access_token; + + if (!isset($fields['url_resource_owner_details']) || empty($fields['url_resource_owner_details'])) { + $fields['url_resource_owner_details'] = $value; + } + + $fields = Plugin::doHookFunction("sso:url_resource_owner_details", $fields); + + $url = $fields['url_resource_owner_details']; + + $url = str_replace("", $access_token, $url); + $url = str_replace("", hash_hmac('sha256', $access_token, $this->getClientSecret()), $url); + + return $url; } /** @@ -611,66 +685,39 @@ private function getCurrentURL() { return $currentURL; } - public function prepareProviderInstance(array $options = [], array $collaborators = []) { - global $CFG_GLPI; - - if ($this->_provider === null) { - - $redirect_uri = $this->getCurrentURL(); - - $type = $this->fields['type']; - $default = [ - 'clientId' => $this->fields['client_id'], - 'clientSecret' => $this->fields['client_secret'], - 'redirectUri' => $redirect_uri, - ]; - - if ($type === 'generic') { - $default['urlAuthorize'] = $this->fields['url_authorize']; - $default['urlAccessToken'] = $this->fields['url_access_token']; - $default['urlResourceOwnerDetails'] = $this->fields['url_resource_owner_details']; - } - - if (!empty($this->fields['extra_options'])) { - try { - $extra = json_decode($this->fields['extra_options'], true); - } catch (Exception $ex) { - $extra = []; - } - - if (!empty($extra)) { - $default = array_merge($default, $extra); - } - } - $options = array_merge($default, $options); - - $this->_provider = self::createInstance($type, $options, $collaborators); - } - return $this->_provider; - } - /** * * @return boolean|string */ public function checkAuthorization() { - if ($this->_provider === null) { - return false; + + if (isset($_GET['error'])) { + + $error_description = isset($_GET['error_description']) ? $_GET['error_description'] : __("The action you have requested is not allowed."); + + Html::displayErrorAndDie(__($error_description), true); } if (!isset($_GET['code'])) { - $scope = []; - if (!empty($this->fields['scope'])) { - $scope = explode(',', $this->fields['scope']); - } - - $options = [ - 'scope' => $scope, + $params = [ + 'client_id' => $this->getClientId(), + 'scope' => $this->getScope(), 'state' => Session::getNewCSRFToken(), + 'response_type' => 'code', + 'approval_prompt' => 'auto', + 'redirect_uri' => $this->getCurrentURL(), ]; - $this->_provider->authorize($options); + $params = Plugin::doHookFunction("sso:authorize_params", $params); + + $url = $this->getAuthorizeUrl(); + + $glue = strstr($url, '?') === false ? '?' : '&'; + $url .= $glue . http_build_query($params); + + header('Location: ' . $url); + exit; } // Check given state against previously stored one to mitigate CSRF attack @@ -687,27 +734,52 @@ public function checkAuthorization() { /** * - * @return boolean|\League\OAuth2\Client\Token\AccessToken + * @return boolean|string */ public function getAccessToken() { if ($this->_token !== null) { return $this->_token; } - if ($this->_provider === null || $this->_code === null) { + if ($this->_code === null) { return false; } - $this->_token = $this->_provider->getAccessToken('authorization_code', [ - 'code' => $this->_code + $params = [ + 'client_id' => $this->getClientId(), + 'client_secret' => $this->getClientSecret(), + 'redirect_uri' => $this->getCurrentURL(), + 'grant_type' => 'authorization_code', + 'code' => $this->_code, + ]; + + $params = Plugin::doHookFunction("sso:access_token_params", $params); + + $url = $this->getAccessTokenUrl(); + + $content = Toolbox::callCurl($url, [ + CURLOPT_HTTPHEADER => [ + "Accept: application/json", + ], + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => http_build_query($params), + CURLOPT_SSL_VERIFYHOST => false, + CURLOPT_SSL_VERIFYPEER => false, ]); + try { + $data = json_decode($content, true); + $this->_token = $data['access_token']; + } catch (\Exception $ex) { + return false; + } + return $this->_token; } /** * - * @return boolean|\League\OAuth2\Client\Provider\ResourceOwnerInterface + * @return boolean|array */ public function getResourceOwner() { if ($this->_resource_owner !== null) { @@ -719,19 +791,64 @@ public function getResourceOwner() { return false; } - $this->_resource_owner = $this->_provider->getResourceOwner($token); + $url = $this->getResourceOwnerDetailsUrl($token); + + $headers = [ + "Accept:application/json", + "Authorization:Bearer $token", + ]; + + $headers = Plugin::doHookFunction("sso:resource_owner_header", $headers); + + $content = Toolbox::callCurl($url, [ + CURLOPT_HTTPHEADER => $headers, + CURLOPT_SSL_VERIFYHOST => false, + CURLOPT_SSL_VERIFYPEER => false, + ]); + + try { + $data = json_decode($content, true); + $this->_resource_owner = $data; + } catch (\Exception $ex) { + return false; + } + + if ($this->getClientType() === "linkedin") { + $email_url = "https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))"; + $content = Toolbox::callCurl($email_url, [ + CURLOPT_HTTPHEADER => $headers, + CURLOPT_SSL_VERIFYHOST => false, + CURLOPT_SSL_VERIFYPEER => false, + ]); + + try { + $data = json_decode($content, true); + + $this->_resource_owner['email-address'] = $data['elements'][0]['handle~']['emailAddress']; + } catch (\Exception $ex) { + return false; + } + } return $this->_resource_owner; } public function findUser() { - $resource = $this->getResourceOwner(); + $resource_array = $this->getResourceOwner(); - $resource_array = $resource->toArray(); + if (!$resource_array) { + return false; + } $user = new User(); //First: check linked user + $id = Plugin::doHookFunction("sso:find_user", $resource_array); + + if (is_numeric($id) && $user->getFromDB($id)) { + return $user; + } + $email = false; $email_fields = ['email', 'e-mail', 'email-address']; @@ -753,7 +870,7 @@ public function findUser() { } $login = false; - $login_fields = ['login', 'username']; + $login_fields = ['login', 'username', 'id']; foreach ($login_fields as $field) { if (isset($resource_array[$field]) && is_string($resource_array[$field])) { diff --git a/providers.json b/providers.json new file mode 100644 index 0000000..cc81127 --- /dev/null +++ b/providers.json @@ -0,0 +1,32 @@ +{ + "facebook": { + "url_authorize": "https://www.facebook.com/v2.12/dialog/oauth", + "url_access_token": "https://www.facebook.com/v2.12/oauth/access_token", + "url_resource_owner_details": "https://www.facebook.com/v2.12/me?fields=id,email&access_token=&appsecret_proof=", + "scope": "public_profile,email" + }, + "github": { + "url_authorize": "https://github.com/login/oauth/authorize", + "url_access_token": "https://github.com/login/oauth/access_token", + "url_resource_owner_details": "https://api.github.com/user", + "scope": "user:email" + }, + "google": { + "url_authorize": "https://accounts.google.com/o/oauth2/v2/auth", + "url_access_token": "https://www.googleapis.com/oauth2/v4/token", + "url_resource_owner_details": "https://openidconnect.googleapis.com/v1/userinfo", + "scope": "openid email profile" + }, + "instagram": { + "url_authorize": "https://api.instagram.com/oauth/authorize", + "url_access_token": "https://api.instagram.com/oauth/access_token", + "url_resource_owner_details": "https://api.instagram.com/v1/users/self?access_token=", + "scope": "basic" + }, + "linkedin": { + "url_authorize": "https://www.linkedin.com/oauth/v2/authorization", + "url_access_token": "https://www.linkedin.com/oauth/v2/accessToken", + "url_resource_owner_details": "https://api.linkedin.com/v2/me", + "scope": "r_liteprofile r_emailaddress" + } +}