diff --git a/bin/build-release.sh b/bin/build-release.sh index 44719ad828d104ccc2acd8a0198d0d7b12e26237..3babf12026b925a139d841460ae44fd42aa736ee 100755 --- a/bin/build-release.sh +++ b/bin/build-release.sh @@ -45,6 +45,7 @@ php "$TARGET/composer.phar" install --no-dev --prefer-dist -o -d "$TARGET" # Install external modules php "$TARGET/composer.phar" require --update-no-dev simplesamlphp/simplesamlphp-module-riak +php "$TARGET/composer.phar" require --update-no-dev simplesamlphp/simplesamlphp-module-oauth cd $TARGET npm install diff --git a/modules/oauth/config-template/module_oauth.php b/modules/oauth/config-template/module_oauth.php deleted file mode 100644 index 63327d6be9a83f009b69908ec944ac9f025feb31..0000000000000000000000000000000000000000 --- a/modules/oauth/config-template/module_oauth.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php -/* - * Configuration for the OAuth module. - * - */ - -$config = [ - /* Enable the getUserInfo endpoint. Do not enable unless you know what you do. - * It may give external parties access to userInfo unless properly secured. - */ - 'getUserInfo.enable' => true, - - 'requestTokenDuration' => 60 * 30, // 30 minutes - 'accessTokenDuration' => 60 * 60 * 24, // 24 hours - 'nonceCache' => 60 * 60 * 24 * 14, // 14 days - - // Tag to run storage cleanup script using the cron module... - 'cron_tag' => 'hourly', - - // auth is the idp to use for admin authentication, - // useridattr is the attribute-name that contains the userid as returned from idp - 'auth' => 'default-sp', - 'useridattr', 'user', -]; diff --git a/modules/oauth/default-disable b/modules/oauth/default-disable deleted file mode 100644 index fa0bd82e2df7bd79d57593d35bc53c1f9d3ef71f..0000000000000000000000000000000000000000 --- a/modules/oauth/default-disable +++ /dev/null @@ -1,3 +0,0 @@ -This file indicates that the default state of this module -is disabled. To enable, create a file named enable in the -same directory as this file. diff --git a/modules/oauth/hooks/hook_cron.php b/modules/oauth/hooks/hook_cron.php deleted file mode 100644 index 1a37cb41d6e4777583b75d23cad64f509ed2fc87..0000000000000000000000000000000000000000 --- a/modules/oauth/hooks/hook_cron.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/** - * Hook to run a cron job. - * - * @param array &$croninfo Output - */ - -function oauth_hook_cron(&$croninfo) -{ - assert(is_array($croninfo)); - assert(array_key_exists('summary', $croninfo)); - assert(array_key_exists('tag', $croninfo)); - - $oauthconfig = \SimpleSAML\Configuration::getOptionalConfig('module_statistics.php'); - - if (is_null($oauthconfig->getValue('cron_tag', 'hourly'))) { - return; - } - if ($oauthconfig->getValue('cron_tag', null) !== $croninfo['tag']) { - return; - } - - try { - $store = new \SimpleSAML\Module\core\Storage\SQLPermanentStorage('oauth'); - $cleaned = $store->removeExpired(); - $croninfo['summary'][] = 'OAuth clean up. Removed '.$cleaned.' expired entries from OAuth storage.'; - } catch (\Exception $e) { - $message = 'OAuth clean up cron script failed: '.$e->getMessage(); - \SimpleSAML\Logger::warning($message); - $croninfo['summary'][] = $message; - } -} diff --git a/modules/oauth/hooks/hook_frontpage.php b/modules/oauth/hooks/hook_frontpage.php deleted file mode 100644 index 028e11c85d0750157741bb07f5b5cffe20ca6cbf..0000000000000000000000000000000000000000 --- a/modules/oauth/hooks/hook_frontpage.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php -/** - * Hook to add link to the frontpage. - * - * @param array &$links The links on the frontpage, split into sections. - */ -function oauth_hook_frontpage(&$links) -{ - assert(is_array($links)); - assert(array_key_exists('links', $links)); - - $links['federation']['oauthregistry'] = [ - 'href' => SimpleSAML\Module::getModuleURL('oauth/registry.php'), - 'text' => '{core:frontpage:link_oauth}', - ]; -} diff --git a/modules/oauth/lib/Consumer.php b/modules/oauth/lib/Consumer.php deleted file mode 100644 index b3a4080ae6c384a48b3971fcc51c9354d1ac5f4d..0000000000000000000000000000000000000000 --- a/modules/oauth/lib/Consumer.php +++ /dev/null @@ -1,179 +0,0 @@ -<?php - -namespace SimpleSAML\Module\oauth; - -require_once(dirname(dirname(__FILE__)).'/libextinc/OAuth.php'); - -/** - * OAuth Consumer - * - * @author Andreas Ă…kre Solberg, <andreas.solberg@uninett.no>, UNINETT AS. - * @package SimpleSAMLphp - */ - -class Consumer -{ - private $consumer; - private $signer; - - public function __construct($key, $secret) - { - $this->consumer = new \OAuthConsumer($key, $secret, null); - $this->signer = new \OAuthSignatureMethod_HMAC_SHA1(); - } - - // Used only to load the libextinc library early - public static function dummy() - { - } - - public static function getOAuthError($hrh) - { - foreach ($hrh as $h) { - if (preg_match('|OAuth-Error:\s([^;]*)|i', $h, $matches)) { - return $matches[1]; - } - } - return null; - } - - public static function getContentType($hrh) - { - foreach ($hrh as $h) { - if (preg_match('|Content-Type:\s([^;]*)|i', $h, $matches)) { - return $matches[1]; - } - } - return null; - } - - /* - * This static helper function wraps \SimpleSAML\Utils\HTTP::fetch - * and throws an exception with diagnostics messages if it appear - * to be failing on an OAuth endpoint. - * - * If the status code is not 200, an exception is thrown. If the content-type - * of the response if text/plain, the content of the response is included in - * the text of the Exception thrown. - */ - public static function getHTTP($url, $context = '') - { - try { - $response = \SimpleSAML\Utils\HTTP::fetch($url); - } catch (\SimpleSAML\Error\Exception $e) { - $statuscode = 'unknown'; - if (preg_match('/^HTTP.*\s([0-9]{3})/', $http_response_header[0], $matches)) { - $statuscode = $matches[1]; - } - - $error = $context.' [statuscode: '.$statuscode.']: '; - $oautherror = self::getOAuthError($http_response_header); - - if (!empty($oautherror)) { - $error .= $oautherror; - } - - throw new \Exception($error.':'.$url); - } - // Fall back to return response, if could not reckognize HTTP header. Should not happen. - return $response; - } - - public function getRequestToken($url, $parameters = null) - { - $req_req = \OAuthRequest::from_consumer_and_token($this->consumer, null, "GET", $url, $parameters); - $req_req->sign_request($this->signer, $this->consumer, null); - - $response_req = self::getHTTP( - $req_req->to_url(), - 'Contacting request_token endpoint on the OAuth Provider' - ); - - parse_str($response_req, $responseParsed); - - if (array_key_exists('error', $responseParsed)) { - throw new \Exception('Error getting request token: '.$responseParsed['error']); - } - - $requestToken = $responseParsed['oauth_token']; - $requestTokenSecret = $responseParsed['oauth_token_secret']; - - return new \OAuthToken($requestToken, $requestTokenSecret); - } - - public function getAuthorizeRequest($url, $requestToken, $redirect = true, $callback = null) - { - $params = ['oauth_token' => $requestToken->key]; - if ($callback) { - $params['oauth_callback'] = $callback; - } - $authorizeURL = \SimpleSAML\Utils\HTTP::addURLParameters($url, $params); - if ($redirect) { - \SimpleSAML\Utils\HTTP::redirectTrustedURL($authorizeURL); - exit; - } - return $authorizeURL; - } - - public function getAccessToken($url, $requestToken, $parameters = null) - { - $acc_req = \OAuthRequest::from_consumer_and_token($this->consumer, $requestToken, "GET", $url, $parameters); - $acc_req->sign_request($this->signer, $this->consumer, $requestToken); - - try { - $response_acc = \SimpleSAML\Utils\HTTP::fetch($acc_req->to_url()); - } catch (\SimpleSAML\Error\Exception $e) { - throw new \Exception('Error contacting request_token endpoint on the OAuth Provider'); - } - - \SimpleSAML\Logger::debug('oauth: Reponse to get access token: '.$response_acc); - - parse_str($response_acc, $accessResponseParsed); - - if (array_key_exists('error', $accessResponseParsed)) { - throw new \Exception('Error getting request token: '.$accessResponseParsed['error']); - } - - $accessToken = $accessResponseParsed['oauth_token']; - $accessTokenSecret = $accessResponseParsed['oauth_token_secret']; - - return new \OAuthToken($accessToken, $accessTokenSecret); - } - - public function postRequest($url, $accessToken, $parameters) - { - $data_req = \OAuthRequest::from_consumer_and_token($this->consumer, $accessToken, "POST", $url, $parameters); - $data_req->sign_request($this->signer, $this->consumer, $accessToken); - $postdata = $data_req->to_postdata(); - - $opts = [ - 'ssl' => [ - 'verify_peer' => false, - 'capture_peer_cert' => true, - 'capture_peer_chain' => true - ], - 'http' => [ - 'method' => 'POST', - 'content' => $postdata, - 'header' => 'Content-Type: application/x-www-form-urlencoded', - ], - ]; - - try { - $response = \SimpleSAML\Utils\HTTP::fetch($url, $opts); - } catch (\SimpleSAML\Error\Exception $e) { - throw new \SimpleSAML\Error\Exception('Failed to push definition file to '.$url); - } - return $response; - } - - public function getUserInfo($url, $accessToken, $opts = null) - { - $data_req = \OAuthRequest::from_consumer_and_token($this->consumer, $accessToken, "GET", $url, null); - $data_req->sign_request($this->signer, $this->consumer, $accessToken); - - $data = \SimpleSAML\Utils\HTTP::fetch($data_req->to_url(), $opts); - - return json_decode($data, true); - } -} diff --git a/modules/oauth/lib/OAuthServer.php b/modules/oauth/lib/OAuthServer.php deleted file mode 100644 index 41e60383ad92a01ebecc95fb7695f5d6c14c59eb..0000000000000000000000000000000000000000 --- a/modules/oauth/lib/OAuthServer.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -namespace SimpleSAML\Module\oauth; - -require_once(dirname(dirname(__FILE__)).'/libextinc/OAuth.php'); - -/** - * OAuth Provider implementation.. - * - * @author Andreas Ă…kre Solberg, <andreas.solberg@uninett.no>, UNINETT AS. - * @package SimpleSAMLphp - */ - -class OAuthServer extends \OAuthServer -{ - public function __construct($store) - { - parent::__construct($store); - } - - public function get_signature_methods() - { - return $this->signature_methods; - } -} diff --git a/modules/oauth/lib/OAuthStore.php b/modules/oauth/lib/OAuthStore.php deleted file mode 100644 index b0c9d222dd5176dd343878a774309676bf03eb2c..0000000000000000000000000000000000000000 --- a/modules/oauth/lib/OAuthStore.php +++ /dev/null @@ -1,213 +0,0 @@ -<?php - -namespace SimpleSAML\Module\oauth; - -require_once(dirname(dirname(__FILE__)).'/libextinc/OAuth.php'); - -/** - * OAuth Store - * - * Updated version, works with consumer-callbacks, certificates and 1.0-RevA protocol - * behaviour (requestToken-callbacks and verifiers) - * - * @author Andreas Ă…kre Solberg, <andreas.solberg@uninett.no>, UNINETT AS. - * @author Mark Dobrinic, <mdobrinic@cozmanova.com>, Cozmanova bv - * @package SimpleSAMLphp - */ - -class OAuthStore extends \OAuthDataStore -{ - private $store; - private $config; - private $defaultversion = '1.0'; - - protected $_store_tables = [ - 'consumers' => 'consumer = array with consumer attributes', - 'nonce' => 'nonce+consumer_key = -boolean-', - 'requesttorequest' => 'requestToken.key = array(version,callback,consumerKey,)', - 'authorized' => 'requestToken.key, verifier = array(authenticated-user-attributes)', - 'access' => 'accessToken.key+consumerKey = accesstoken', - 'request' => 'requestToken.key+consumerKey = requesttoken', - ]; - - - public function __construct() - { - $this->store = new \SimpleSAML\Module\core\Storage\SQLPermanentStorage('oauth'); - $this->config = \SimpleSAML\Configuration::getOptionalConfig('module_oauth.php'); - } - - - /** - * Attach the data to the token, and establish the Callback URL and verifier - * @param string $requestTokenKey RequestToken that was authorized - * @param string $data Data that is authorized and to be attached to the requestToken - * @return array(string:url, string:verifier) ; empty verifier for 1.0-response - */ - public function authorize($requestTokenKey, $data) - { - $url = null; - - // See whether to remember values from the original requestToken request: - $request_attributes = $this->store->get('requesttorequest', $requestTokenKey, ''); - // must be there - if ($request_attributes['value']) { - // establish callback to use - if ($request_attributes['value']['callback']) { - $url = $request_attributes['value']['callback']; - } - } - - // Is there a callback registered? This is leading, even over a supplied oauth_callback-parameter - $oConsumer = $this->lookup_consumer($request_attributes['value']['consumerKey']); - - if ($oConsumer && ($oConsumer->callback_url)) { - $url = $oConsumer->callback_url; - } - - $verifier = \SimpleSAML\Utils\Random::generateID(); - $url = \SimpleSAML\Utils\HTTP::addURLParameters($url, ["oauth_verifier"=>$verifier]); - - $this->store->set('authorized', $requestTokenKey, $verifier, $data, $this->config->getValue('requestTokenDuration', 1800)); //60*30=1800 - - return [$url, $verifier]; - } - - /** - * Perform lookup whether a given token exists in the list of authorized tokens; if a verifier is - * passed as well, the verifier *must* match the verifier that was registered with the token<br/> - * Note that an accessToken should never be stored with a verifier - * @param string $requestToken - * @param string $verifier - * @return bool - */ - public function isAuthorized($requestToken, $verifier = '') - { - \SimpleSAML\Logger::info('OAuth isAuthorized('.$requestToken.')'); - return $this->store->exists('authorized', $requestToken, $verifier); - } - - public function getAuthorizedData($token, $verifier = '') - { - \SimpleSAML\Logger::info('OAuth getAuthorizedData('.$token.')'); - $data = $this->store->get('authorized', $token, $verifier); - return $data['value']; - } - - public function moveAuthorizedData($requestToken, $verifier, $accessTokenKey) - { - \SimpleSAML\Logger::info('OAuth moveAuthorizedData('.$requestToken.', '.$accessTokenKey.')'); - - // Retrieve authorizedData from authorized.requestToken (with provider verifier) - $authorizedData = $this->getAuthorizedData($requestToken, $verifier); - - // Remove the requesttoken+verifier from authorized store - $this->store->remove('authorized', $requestToken, $verifier); - - // Add accesstoken with authorizedData to authorized store (with empty verifier) - // accessTokenKey+consumer => accessToken is already registered in 'access'-table - $this->store->set('authorized', $accessTokenKey, '', $authorizedData, $this->config->getValue('accessTokenDuration', 86400)); //60*60*24=86400 - } - - public function lookup_consumer($consumer_key) - { - \SimpleSAML\Logger::info('OAuth lookup_consumer('.$consumer_key.')'); - if (!$this->store->exists('consumers', $consumer_key, '')) { - return null; - } - $consumer = $this->store->get('consumers', $consumer_key, ''); - - $callback = null; - if ($consumer['value']['callback_url']) { - $callback = $consumer['value']['callback_url']; - } - - if ($consumer['value']['RSAcertificate']) { - return new \OAuthConsumer($consumer['value']['key'], $consumer['value']['RSAcertificate'], $callback); - } else { - return new \OAuthConsumer($consumer['value']['key'], $consumer['value']['secret'], $callback); - } - } - - public function lookup_token($consumer, $tokenType = 'default', $token) - { - \SimpleSAML\Logger::info('OAuth lookup_token('.$consumer->key.', '.$tokenType.','.$token.')'); - $data = $this->store->get($tokenType, $token, $consumer->key); - if ($data == null) { - throw new \Exception('Could not find token'); - } - return $data['value']; - } - - public function lookup_nonce($consumer, $token, $nonce, $timestamp) - { - \SimpleSAML\Logger::info('OAuth lookup_nonce('.$consumer.', '.$token.','.$nonce.')'); - if ($this->store->exists('nonce', $nonce, $consumer->key)) { - return true; - } - $this->store->set('nonce', $nonce, $consumer->key, true, $this->config->getValue('nonceCache', 1209600)); //60*60*24*14=1209600 - return false; - } - - public function new_request_token($consumer, $callback = null, $version = null) - { - \SimpleSAML\Logger::info('OAuth new_request_token('.$consumer.')'); - - $lifetime = $this->config->getValue('requestTokenDuration', 1800); //60*30 - - $token = new \OAuthToken(\SimpleSAML\Utils\Random::generateID(), \SimpleSAML\Utils\Random::generateID()); - $token->callback = $callback; // OAuth1.0-RevA - $this->store->set('request', $token->key, $consumer->key, $token, $lifetime); - - // also store in requestToken->key => array('callback'=>CallbackURL, 'version'=>oauth_version - $request_attributes = [ - 'callback' => $callback, - 'version' => ($version ? $version : $this->defaultversion), - 'consumerKey' => $consumer->key, - ]; - $this->store->set('requesttorequest', $token->key, '', $request_attributes, $lifetime); - - /* also store in requestToken->key => - * Consumer->key (enables consumer-lookup during reqToken-authorization stage) - */ - $this->store->set('requesttoconsumer', $token->key, '', $consumer->key, $lifetime); - - return $token; - } - - public function new_access_token($requestToken, $consumer, $verifier = null) - { - \SimpleSAML\Logger::info('OAuth new_access_token('.$requestToken.','.$consumer.')'); - $accesstoken = new \OAuthToken(\SimpleSAML\Utils\Random::generateID(), \SimpleSAML\Utils\Random::generateID()); - $this->store->set( - 'access', - $accesstoken->key, - $consumer->key, - $accesstoken, - $this->config->getValue('accessTokenDuration', 86400) //60*60*24=86400 - ); - return $accesstoken; - } - - /** - * Return OAuthConsumer-instance that a given requestToken was issued to - * @param string $requestTokenKey - * @return mixed - */ - public function lookup_consumer_by_requestToken($requestTokenKey) - { - \SimpleSAML\Logger::info('OAuth lookup_consumer_by_requestToken('.$requestTokenKey.')'); - if (!$this->store->exists('requesttorequest', $requestTokenKey, '')) { - return null; - } - - $request = $this->store->get('requesttorequest', $requestTokenKey, ''); - $consumerKey = $request['value']['consumerKey']; - if (!$consumerKey) { - return null; - } - - $consumer = $this->store->get('consumers', $consumerKey['value'], ''); - return $consumer['value']; - } -} diff --git a/modules/oauth/lib/Registry.php b/modules/oauth/lib/Registry.php deleted file mode 100644 index 0939be6f410ce90c587c388c7ffa15e7cbc89c12..0000000000000000000000000000000000000000 --- a/modules/oauth/lib/Registry.php +++ /dev/null @@ -1,151 +0,0 @@ -<?php - -namespace SimpleSAML\Module\oauth; - -/** - * Editor for OAuth Client Registry - * - * @author Andreas Ă…kre Solberg <andreas@uninett.no>, UNINETT AS. - * @package SimpleSAMLphp - */ - -class Registry -{ - public static function requireOwnership($entry, $userid) - { - if (!isset($entry['owner'])) { - throw new \Exception('OAuth Consumer has no owner. Which means no one is granted access, not even you.'); - } elseif ($entry['owner'] !== $userid) { - throw new \Exception( - 'OAuth Consumer has an owner that is not equal to your userid, hence you are not granted access.' - ); - } - } - - protected function getStandardField($request, &$entry, $key) - { - if (array_key_exists('field_'.$key, $request)) { - $entry[$key] = $request['field_'.$key]; - } elseif (isset($entry[$key])) { - unset($entry[$key]); - } - } - - public function formToMeta($request, $entry = [], $override = null) - { - $this->getStandardField($request, $entry, 'name'); - $this->getStandardField($request, $entry, 'description'); - $this->getStandardField($request, $entry, 'key'); - $this->getStandardField($request, $entry, 'secret'); - $this->getStandardField($request, $entry, 'RSAcertificate'); - $this->getStandardField($request, $entry, 'callback_url'); - - if ($override) { - foreach ($override as $key => $value) { - $entry[$key] = $value; - } - } - return $entry; - } - - protected function requireStandardField($request, $key) - { - if (!array_key_exists('field_'.$key, $request)) { - throw new \Exception('Required field ['.$key.'] was missing.'); - } - if (empty($request['field_'.$key])) { - throw new \Exception('Required field ['.$key.'] was empty.'); - } - } - - public function checkForm($request) - { - $this->requireStandardField($request, 'name'); - $this->requireStandardField($request, 'description'); - $this->requireStandardField($request, 'key'); - } - - protected function header($name) - { - return '<tr><td> </td><td class="header">'.$name.'</td></tr>'; - } - - protected function readonlyDateField($metadata, $key, $name) - { - $value = '<span style="color: #aaa">Not set</a>'; - if (array_key_exists($key, $metadata)) { - $value = date('j. F Y, G:i', $metadata[$key]); - } - return '<tr><td class="name">'.$name.'</td><td class="data">'.$value.'</td></tr>'; - } - - protected function readonlyField($metadata, $key, $name) - { - $value = ''; - if (array_key_exists($key, $metadata)) { - $value = $metadata[$key]; - } - return '<tr><td class="name">'.$name.'</td><td class="data">'.htmlspecialchars($value).'</td></tr>'; - } - - protected function hiddenField($key, $value) - { - return '<input type="hidden" name="'.$key.'" value="'.htmlspecialchars($value).'" />'; - } - - protected function flattenLanguageField(&$metadata, $key) - { - if (array_key_exists($key, $metadata)) { - if (is_array($metadata[$key])) { - if (isset($metadata[$key]['en'])) { - $metadata[$key] = $metadata[$key]['en']; - } else { - unset($metadata[$key]); - } - } - } - } - - protected function standardField($metadata, $key, $name, $textarea = false) - { - $value = ''; - if (array_key_exists($key, $metadata)) { - $value = htmlspecialchars($metadata[$key]); - } - - if ($textarea) { - return '<tr><td class="name">'.$name.'</td><td class="data"> - <textarea name="field_'.$key.'" rows="5" cols="50">'.$value.'</textarea></td></tr>'; - } else { - return '<tr><td class="name">'.$name.'</td><td class="data"> - <input type="text" size="60" name="field_'.$key.'" value="'.$value.'" /></td></tr>'; - } - } - - public function metaToForm($metadata) - { - return '<form action="registry.edit.php" method="post">'. - '<div id="tabdiv">'. - '<ul class="tabset_tabs">'. - '<li class="tab-link current" data-tab="basic"><a href="#basic">Name and description</a></li>'. - '</ul>'. - '<div id="basic" class="tabset_content current"><table class="formtable">'. - $this->standardField($metadata, 'name', 'Name of client'). - $this->standardField($metadata, 'description', 'Description of client', true). - $this->readonlyField($metadata, 'owner', 'Owner'). - $this->standardField($metadata, 'key', 'Consumer Key'). - $this->readonlyField($metadata, 'secret', 'Consumer Secret<br />(Used for HMAC_SHA1 signatures)'). - $this->standardField( - $metadata, - 'RSAcertificate', - 'RSA certificate (PEM)<br />(Used for RSA_SHA1 signatures)', - true - ). - $this->standardField($metadata, 'callback_url', 'Static/enforcing callback-url'). - '</table></div>'. - '</div>'. - $this->hiddenField('field_secret', $metadata['secret']). - '<input type="submit" name="submit" value="Save" style="margin-top: 5px" />'. - '</form>'; - } -} diff --git a/modules/oauth/libextinc/LICENSE.txt b/modules/oauth/libextinc/LICENSE.txt deleted file mode 100644 index 89f0591697f2a550b2003c9e05c778f367aac189..0000000000000000000000000000000000000000 --- a/modules/oauth/libextinc/LICENSE.txt +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License - -Copyright (c) 2007 Andy Smith - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission 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. - diff --git a/modules/oauth/libextinc/OAuth.php b/modules/oauth/libextinc/OAuth.php deleted file mode 100644 index c8811d6ce1263032e6fe32c9227546a5014ad945..0000000000000000000000000000000000000000 --- a/modules/oauth/libextinc/OAuth.php +++ /dev/null @@ -1,991 +0,0 @@ -<?php -/** - * @file - * OAuth 1.0 server and client library. - */ - -/** - * OAuth PECL extension includes an OAuth Exception class, so we need to wrap - * the definition of this class in order to avoid a PHP error. - */ -if (!class_exists('OAuthException')) { - /* - * Generic exception class - */ - class OAuthException extends Exception - { - // pass - } -} - -if (!class_exists('OAuthConsumer')) { - class OAuthConsumer - { - public $key; - public $secret; - public $callback_url; - - public function __construct($key, $secret, $callback_url = null) - { - $this->key = $key; - $this->secret = $secret; - $this->callback_url = $callback_url; - } - - public function __toString() - { - return "OAuthConsumer[key=$this->key,secret=$this->secret]"; - } - } -} - -class OAuthToken -{ - // access tokens and request tokens - public $key; - public $secret; - - /** - * key = the token - * secret = the token secret - */ - public function __construct($key, $secret) - { - $this->key = $key; - $this->secret = $secret; - } - - /** - * generates the basic string serialization of a token that a server - * would respond to request_token and access_token calls with - */ - public function to_string() - { - return "oauth_token=". - OAuthUtil::urlencode_rfc3986($this->key). - "&oauth_token_secret=". - OAuthUtil::urlencode_rfc3986($this->secret). - "&oauth_callback_confirmed=true"; - } - - public function __toString() - { - return $this->to_string(); - } -} - -/** - * A class for implementing a Signature Method - * See section 9 ("Signing Requests") in the spec - */ -abstract class OAuthSignatureMethod -{ - /** - * Needs to return the name of the Signature Method (ie HMAC-SHA1) - * @return string - */ - abstract public function get_name(); - - /** - * Build up the signature - * NOTE: The output of this function MUST NOT be urlencoded. - * the encoding is handled in OAuthRequest when the final - * request is serialized - * @param OAuthRequest $request - * @param OAuthConsumer $consumer - * @param OAuthToken $token - * @return string - */ - abstract public function build_signature($request, $consumer, $token); - - /** - * Verifies that a given signature is correct - * @param OAuthRequest $request - * @param OAuthConsumer $consumer - * @param OAuthToken $token - * @param string $signature - * @return bool - */ - public function check_signature($request, $consumer, $token, $signature) - { - $built = $this->build_signature($request, $consumer, $token); - - // Check for zero length, although unlikely here - if (strlen($built) == 0 || strlen($signature) == 0) { - return false; - } - - if (strlen($built) != strlen($signature)) { - return false; - } - - // Avoid a timing leak with a (hopefully) time insensitive compare - $result = 0; - for ($i = 0; $i < strlen($signature); $i++) { - $result |= ord($built{$i}) ^ ord($signature{$i}); - } - - return $result == 0; - } -} - -/** - * The HMAC-SHA1 signature method uses the HMAC-SHA1 signature algorithm as defined in [RFC2104] - * where the Signature Base String is the text and the key is the concatenated values (each first - * encoded per Parameter Encoding) of the Consumer Secret and Token Secret, separated by an '&' - * character (ASCII code 38) even if empty. - * - Chapter 9.2 ("HMAC-SHA1") - */ -class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod -{ - public function get_name() - { - return "HMAC-SHA1"; - } - - public function build_signature($request, $consumer, $token) - { - $base_string = $request->get_signature_base_string(); - $request->base_string = $base_string; - - $key_parts = [ - $consumer->secret, - ($token) ? $token->secret : "" - ]; - - $key_parts = OAuthUtil::urlencode_rfc3986($key_parts); - $key = implode('&', $key_parts); - - return base64_encode(hash_hmac('sha1', $base_string, $key, true)); - } -} - -/** - * The PLAINTEXT method does not provide any security protection and SHOULD only be used - * over a secure channel such as HTTPS. It does not use the Signature Base String. - * - Chapter 9.4 ("PLAINTEXT") - */ -class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod -{ - public function get_name() - { - return "PLAINTEXT"; - } - - /** - * oauth_signature is set to the concatenated encoded values of the Consumer Secret and - * Token Secret, separated by a '&' character (ASCII code 38), even if either secret is - * empty. The result MUST be encoded again. - * - Chapter 9.4.1 ("Generating Signatures") - * - * Please note that the second encoding MUST NOT happen in the SignatureMethod, as - * OAuthRequest handles this! - */ - public function build_signature($request, $consumer, $token) - { - $key_parts = [ - $consumer->secret, - ($token) ? $token->secret : "" - ]; - - $key_parts = OAuthUtil::urlencode_rfc3986($key_parts); - $key = implode('&', $key_parts); - $request->base_string = $key; - - return $key; - } -} - -/** - * The RSA-SHA1 signature method uses the RSASSA-PKCS1-v1_5 signature algorithm as defined in - * [RFC3447] section 8.2 (more simply known as PKCS#1), using SHA-1 as the hash function for - * EMSA-PKCS1-v1_5. It is assumed that the Consumer has provided its RSA public key in a - * verified way to the Service Provider, in a manner which is beyond the scope of this - * specification. - * - Chapter 9.3 ("RSA-SHA1") - */ -abstract class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod -{ - public function get_name() - { - return "RSA-SHA1"; - } - - // Up to the SP to implement this lookup of keys. Possible ideas are: - // (1) do a lookup in a table of trusted certs keyed off of consumer - // (2) fetch via http using a url provided by the requester - // (3) some sort of specific discovery code based on request - // - // Either way should return a string representation of the certificate - abstract protected function fetch_public_cert(&$request); - - // Up to the SP to implement this lookup of keys. Possible ideas are: - // (1) do a lookup in a table of trusted certs keyed off of consumer - // - // Either way should return a string representation of the certificate - abstract protected function fetch_private_cert(&$request); - - public function build_signature($request, $consumer, $token) - { - $base_string = $request->get_signature_base_string(); - $request->base_string = $base_string; - - // Fetch the private key cert based on the request - $cert = $this->fetch_private_cert($request); - - // Pull the private key ID from the certificate - $privatekeyid = openssl_get_privatekey($cert); - - // Sign using the key - openssl_sign($base_string, $signature, $privatekeyid); - - // Release the key resource - openssl_free_key($privatekeyid); - - return base64_encode($signature); - } - - public function check_signature($request, $consumer, $token, $signature) - { - $decoded_sig = base64_decode($signature); - - $base_string = $request->get_signature_base_string(); - - // Fetch the public key cert based on the request - $cert = $this->fetch_public_cert($request); - - // Pull the public key ID from the certificate - $publickeyid = openssl_get_publickey($cert); - - // Check the computed signature against the one passed in the query - $ok = openssl_verify($base_string, $decoded_sig, $publickeyid); - - // Release the key resource - openssl_free_key($publickeyid); - - return $ok == 1; - } -} - -class OAuthRequest -{ - protected $parameters; - protected $http_method; - protected $http_url; - // for debug purposes - public $base_string; - public static $version = '1.0'; - public static $POST_INPUT = 'php://input'; - - public function __construct($http_method, $http_url, $parameters = null) - { - $parameters = ($parameters) ? $parameters : []; - $parameters = array_merge(OAuthUtil::parse_parameters(parse_url($http_url, PHP_URL_QUERY)), $parameters); - $this->parameters = $parameters; - $this->http_method = $http_method; - $this->http_url = $http_url; - } - - - /** - * attempt to build up a request from what was passed to the server - */ - public static function from_request($http_method = null, $http_url = null, $parameters = null) - { - $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") - ? 'http' - : 'https'; - $http_url = ($http_url) ? $http_url : $scheme. - '://'.$_SERVER['SERVER_NAME']. - ':'. - $_SERVER['SERVER_PORT']. - $_SERVER['REQUEST_URI']; - $http_method = ($http_method) ? $http_method : $_SERVER['REQUEST_METHOD']; - - // We weren't handed any parameters, so let's find the ones relevant to - // this request. - // If you run XML-RPC or similar you should use this to provide your own - // parsed parameter-list - if (!$parameters) { - // Find request headers - $request_headers = OAuthUtil::get_headers(); - - // Parse the query-string to find GET parameters - $parameters = OAuthUtil::parse_parameters($_SERVER['QUERY_STRING']); - - // It's a POST request of the proper content-type, so parse POST - // parameters and add those overriding any duplicates from GET - if ($http_method == "POST" - && isset($request_headers['Content-Type']) - && strstr($request_headers['Content-Type'], 'application/x-www-form-urlencoded') - ) { - $post_data = OAuthUtil::parse_parameters( - file_get_contents(self::$POST_INPUT) - ); - $parameters = array_merge($parameters, $post_data); - } - - // We have a Authorization-header with OAuth data. Parse the header - // and add those overriding any duplicates from GET or POST - if (isset($request_headers['Authorization']) - && substr($request_headers['Authorization'], 0, 6) == 'OAuth ' - ) { - $header_parameters = OAuthUtil::split_header( - $request_headers['Authorization'] - ); - $parameters = array_merge($parameters, $header_parameters); - } - } - - return new OAuthRequest($http_method, $http_url, $parameters); - } - - /** - * pretty much a helper function to set up the request - */ - public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters = null) - { - $parameters = ($parameters) ? $parameters : []; - $defaults = ["oauth_version" => OAuthRequest::$version, - "oauth_nonce" => OAuthRequest::generate_nonce(), - "oauth_timestamp" => OAuthRequest::generate_timestamp(), - "oauth_consumer_key" => $consumer->key]; - if ($token) { - $defaults['oauth_token'] = $token->key; - } - - $parameters = array_merge($defaults, $parameters); - - return new OAuthRequest($http_method, $http_url, $parameters); - } - - public function set_parameter($name, $value, $allow_duplicates = true) - { - if ($allow_duplicates && isset($this->parameters[$name])) { - // We have already added parameter(s) with this name, so add to the list - if (is_scalar($this->parameters[$name])) { - // This is the first duplicate, so transform scalar (string) - // into an array so we can add the duplicates - $this->parameters[$name] = [$this->parameters[$name]]; - } - - $this->parameters[$name][] = $value; - } else { - $this->parameters[$name] = $value; - } - } - - public function get_parameter($name) - { - return isset($this->parameters[$name]) ? $this->parameters[$name] : null; - } - - public function get_parameters() - { - return $this->parameters; - } - - public function unset_parameter($name) - { - unset($this->parameters[$name]); - } - - /** - * The request parameters, sorted and concatenated into a normalized string. - * @return string - */ - public function get_signable_parameters() - { - // Grab all parameters - $params = $this->parameters; - - // Remove oauth_signature if present - // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.") - if (isset($params['oauth_signature'])) { - unset($params['oauth_signature']); - } - - return OAuthUtil::build_http_query($params); - } - - /** - * Returns the base string of this request - * - * The base string defined as the method, the url - * and the parameters (normalized), each urlencoded - * and the concated with &. - */ - public function get_signature_base_string() - { - $parts = [ - $this->get_normalized_http_method(), - $this->get_normalized_http_url(), - $this->get_signable_parameters() - ]; - - $parts = OAuthUtil::urlencode_rfc3986($parts); - - return implode('&', $parts); - } - - /** - * just uppercases the http method - */ - public function get_normalized_http_method() - { - return strtoupper($this->http_method); - } - - /** - * parses the url and rebuilds it to be - * scheme://host/path - */ - public function get_normalized_http_url() - { - $parts = parse_url($this->http_url); - - $scheme = (isset($parts['scheme'])) ? $parts['scheme'] : 'http'; - $port = (isset($parts['port'])) ? $parts['port'] : (($scheme == 'https') ? '443' : '80'); - $host = (isset($parts['host'])) ? strtolower($parts['host']) : ''; - $path = (isset($parts['path'])) ? $parts['path'] : ''; - - if (($scheme == 'https' && $port != '443') - || ($scheme == 'http' && $port != '80')) { - $host = "$host:$port"; - } - return "$scheme://$host$path"; - } - - /** - * builds a url usable for a GET request - */ - public function to_url() - { - $post_data = $this->to_postdata(); - $out = $this->get_normalized_http_url(); - if ($post_data) { - $out .= '?'.$post_data; - } - return $out; - } - - /** - * builds the data one would send in a POST request - */ - public function to_postdata() - { - return OAuthUtil::build_http_query($this->parameters); - } - - /** - * builds the Authorization: header - */ - public function to_header($realm = null) - { - $first = true; - if ($realm) { - $out = 'Authorization: OAuth realm="'.OAuthUtil::urlencode_rfc3986($realm).'"'; - $first = false; - } else { - $out = 'Authorization: OAuth'; - } - - foreach ($this->parameters as $k => $v) { - if (substr($k, 0, 5) != "oauth") { - continue; - } - if (is_array($v)) { - throw new OAuthException('Arrays not supported in headers'); - } - $out .= ($first) ? ' ' : ','; - $out .= OAuthUtil::urlencode_rfc3986($k). - '="'. - OAuthUtil::urlencode_rfc3986($v). - '"'; - $first = false; - } - return $out; - } - - public function __toString() - { - return $this->to_url(); - } - - - public function sign_request($signature_method, $consumer, $token) - { - $this->set_parameter( - "oauth_signature_method", - $signature_method->get_name(), - false - ); - $signature = $this->build_signature($signature_method, $consumer, $token); - $this->set_parameter("oauth_signature", $signature, false); - } - - public function build_signature($signature_method, $consumer, $token) - { - $signature = $signature_method->build_signature($this, $consumer, $token); - return $signature; - } - - /** - * util function: current timestamp - */ - private static function generate_timestamp() - { - return time(); - } - - /** - * util function: current nonce - */ - private static function generate_nonce() - { - $mt = microtime(); - $rand = mt_rand(); - - return md5($mt.$rand); // md5s look nicer than numbers - } -} - -class OAuthServer -{ - protected $timestamp_threshold = 300; // in seconds, five minutes - protected $version = '1.0'; // hi blaine - protected $signature_methods = []; - - protected $data_store; - - public function __construct($data_store) - { - $this->data_store = $data_store; - } - - public function add_signature_method($signature_method) - { - $this->signature_methods[$signature_method->get_name()] = - $signature_method; - } - - // high level functions - - /** - * process a request_token request - * returns the request token on success - */ - public function fetch_request_token(&$request) - { - $this->getVersion($request); - - $consumer = $this->getConsumer($request); - - // no token required for the initial token request - $token = null; - - $this->checkSignature($request, $consumer, $token); - - // Rev A change - $callback = $request->get_parameter('oauth_callback'); - $new_token = $this->data_store->new_request_token($consumer, $callback); - - return $new_token; - } - - /** - * process an access_token request - * returns the access token on success - */ - public function fetch_access_token(&$request) - { - $this->getVersion($request); - - $consumer = $this->getConsumer($request); - - // requires authorized request token - $token = $this->getToken($request, $consumer, "request"); - - $this->checkSignature($request, $consumer, $token); - - // Rev A change - $verifier = $request->get_parameter('oauth_verifier'); - $new_token = $this->data_store->new_access_token($token, $consumer, $verifier); - - return $new_token; - } - - /** - * verify an api call, checks all the parameters - */ - public function verify_request(&$request) - { - $this->getVersion($request); - $consumer = $this->getConsumer($request); - $token = $this->getToken($request, $consumer, "access"); - $this->checkSignature($request, $consumer, $token); - return [$consumer, $token]; - } - - // Internals from here - /** - * version 1 - */ - private function getVersion(&$request) - { - $version = $request->get_parameter("oauth_version"); - if (!$version) { - // Service Providers MUST assume the protocol version to be 1.0 if this parameter is not present. - // Chapter 7.0 ("Accessing Protected Ressources") - $version = '1.0'; - } - if ($version !== $this->version) { - throw new OAuthException("OAuth version '$version' not supported"); - } - return $version; - } - - /** - * figure out the signature with some defaults - */ - private function getSignatureMethod($request) - { - $signature_method = $request instanceof OAuthRequest - ? $request->get_parameter("oauth_signature_method") - : null; - - if (!$signature_method) { - // According to chapter 7 ("Accessing Protected Ressources") the signature-method - // parameter is required, and we can't just fallback to PLAINTEXT - throw new OAuthException('No signature method parameter. This parameter is required'); - } - - if (!in_array($signature_method, array_keys($this->signature_methods))) { - throw new OAuthException( - "Signature method '$signature_method' not supported ". - "try one of the following: ". - implode(", ", array_keys($this->signature_methods)) - ); - } - return $this->signature_methods[$signature_method]; - } - - /** - * try to find the consumer for the provided request's consumer key - */ - private function getConsumer($request) - { - $consumer_key = $request instanceof OAuthRequest - ? $request->get_parameter("oauth_consumer_key") - : null; - - if (!$consumer_key) { - throw new OAuthException("Invalid consumer key"); - } - - $consumer = $this->data_store->lookup_consumer($consumer_key); - if (!$consumer) { - throw new OAuthException("Invalid consumer"); - } - - return $consumer; - } - - /** - * try to find the token for the provided request's token key - */ - private function getToken($request, $consumer, $token_type = "access") - { - $token_field = $request instanceof OAuthRequest - ? $request->get_parameter('oauth_token') - : null; - - if (!empty($token_field)) { - $token = $this->data_store->lookup_token($consumer, $token_type, $token_field); - if (!$token) { - throw new OAuthException('Invalid '.$token_type.' token: '.$token_field); - } - } else { - $token = new OAuthToken('', ''); - } - return $token; - } - - /** - * all-in-one function to check the signature on a request - * should guess the signature method appropriately - */ - private function checkSignature($request, $consumer, $token) - { - // this should probably be in a different method - $timestamp = $request instanceof OAuthRequest - ? $request->get_parameter('oauth_timestamp') - : null; - $nonce = $request instanceof OAuthRequest - ? $request->get_parameter('oauth_nonce') - : null; - - $this->checkTimestamp($timestamp); - $this->checkNonce($consumer, $token, $nonce, $timestamp); - - $signature_method = $this->getSignatureMethod($request); - - $signature = $request->get_parameter('oauth_signature'); - $valid_sig = $signature_method->checkSignature( - $request, - $consumer, - $token, - $signature - ); - - if (!$valid_sig) { - throw new OAuthException("Invalid signature"); - } - } - - /** - * check that the timestamp is new enough - */ - private function checkTimestamp($timestamp) - { - if (!$timestamp) { - throw new OAuthException( - 'Missing timestamp parameter. The parameter is required' - ); - } - - // verify that timestamp is recentish - $now = time(); - if (abs($now - $timestamp) > $this->timestamp_threshold) { - throw new OAuthException( - "Expired timestamp, yours $timestamp, ours $now" - ); - } - } - - /** - * check that the nonce is not repeated - */ - private function checkNonce($consumer, $token, $nonce, $timestamp) - { - if (!$nonce) { - throw new OAuthException( - 'Missing nonce parameter. The parameter is required' - ); - } - - // verify that the nonce is uniqueish - $found = $this->data_store->lookup_nonce( - $consumer, - $token, - $nonce, - $timestamp - ); - if ($found) { - throw new OAuthException("Nonce already used: $nonce"); - } - } -} - -class OAuthDataStore -{ - public function lookup_consumer($consumer_key) - { - // implement me - } - - public function lookup_token($consumer, $token_type, $token) - { - // implement me - } - - public function lookup_nonce($consumer, $token, $nonce, $timestamp) - { - // implement me - } - - public function new_request_token($consumer, $callback = null) - { - // return a new token attached to this consumer - } - - public function new_access_token($token, $consumer, $verifier = null) - { - // return a new access token attached to this consumer - // for the user associated with this token if the request token - // is authorized - // should also invalidate the request token - } -} - -class OAuthUtil -{ - public static function urlencode_rfc3986($input) - { - if (is_array($input)) { - return array_map(['OAuthUtil', 'urlencode_rfc3986'], $input); - } elseif (is_scalar($input)) { - return str_replace( - '+', - ' ', - str_replace('%7E', '~', rawurlencode($input)) - ); - } else { - return ''; - } - } - - - // This decode function isn't taking into consideration the above - // modifications to the encoding process. However, this method doesn't - // seem to be used anywhere so leaving it as is. - public static function urldecode_rfc3986($string) - { - return urldecode($string); - } - - // Utility function for turning the Authorization: header into - // parameters, has to do some unescaping - // Can filter out any non-oauth parameters if needed (default behaviour) - // May 28th, 2010 - method updated to tjerk.meesters for a speed improvement. - // see http://code.google.com/p/oauth/issues/detail?id=163 - public static function split_header($header, $only_allow_oauth_parameters = true) - { - $params = []; - if (preg_match_all( - '/('.($only_allow_oauth_parameters ? 'oauth_' : '').'[a-z_-]*)=(:?"([^"]*)"|([^,]*))/', - $header, - $matches - )) { - foreach ($matches[1] as $i => $h) { - $params[$h] = OAuthUtil::urldecode_rfc3986(empty($matches[3][$i]) ? $matches[4][$i] : $matches[3][$i]); - } - if (isset($params['realm'])) { - unset($params['realm']); - } - } - return $params; - } - - // helper to try to sort out headers for people who aren't running apache - public static function get_headers() - { - if (function_exists('apache_request_headers')) { - // we need this to get the actual Authorization: header - // because apache tends to tell us it doesn't exist - $headers = apache_request_headers(); - - // sanitize the output of apache_request_headers because - // we always want the keys to be Cased-Like-This and arh() - // returns the headers in the same case as they are in the - // request - $out = []; - foreach ($headers as $key => $value) { - $key = str_replace( - " ", - "-", - ucwords(strtolower(str_replace("-", " ", $key))) - ); - $out[$key] = $value; - } - } else { - // otherwise we don't have apache and are just going to have to hope - // that $_SERVER actually contains what we need - $out = []; - if (isset($_SERVER['CONTENT_TYPE'])) { - $out['Content-Type'] = $_SERVER['CONTENT_TYPE']; - } - if (isset($_ENV['CONTENT_TYPE'])) { - $out['Content-Type'] = $_ENV['CONTENT_TYPE']; - } - - foreach ($_SERVER as $key => $value) { - if (substr($key, 0, 5) == "HTTP_") { - // this is chaos, basically it is just there to capitalize the first - // letter of every word that is not an initial HTTP and strip HTTP - // code from przemek - $key = str_replace( - " ", - "-", - ucwords(strtolower(str_replace("_", " ", substr($key, 5)))) - ); - $out[$key] = $value; - } - } - // The "Authorization" header may get turned into "Auth". - if (isset($out['Auth'])) { - $out['Authorization'] = $out['Auth']; - } - } - return $out; - } - - // This function takes a input like a=b&a=c&d=e and returns the parsed - // parameters like this - // array('a' => array('b','c'), 'd' => 'e') - public static function parse_parameters($input) - { - if (!isset($input) || !$input) { - return []; - } - - $pairs = explode('&', $input); - - $parsed_parameters = []; - foreach ($pairs as $pair) { - $split = explode('=', $pair, 2); - $parameter = OAuthUtil::urldecode_rfc3986($split[0]); - $value = isset($split[1]) ? OAuthUtil::urldecode_rfc3986($split[1]) : ''; - - if (isset($parsed_parameters[$parameter])) { - // We have already recieved parameter(s) with this name, so add to the list - // of parameters with this name - - if (is_scalar($parsed_parameters[$parameter])) { - // This is the first duplicate, so transform scalar (string) into an array - // so we can add the duplicates - $parsed_parameters[$parameter] = [$parsed_parameters[$parameter]]; - } - - $parsed_parameters[$parameter][] = $value; - } else { - $parsed_parameters[$parameter] = $value; - } - } - return $parsed_parameters; - } - - public static function build_http_query($params) - { - if (!$params) { - return ''; - } - - // Urlencode both keys and values - $keys = OAuthUtil::urlencode_rfc3986(array_keys($params)); - $values = OAuthUtil::urlencode_rfc3986(array_values($params)); - $params = array_combine($keys, $values); - - // Parameters are sorted by name, using lexicographical byte value ordering. - // Ref: Spec: 9.1.1 (1) - uksort($params, 'strcmp'); - - $pairs = []; - foreach ($params as $parameter => $value) { - if (is_array($value)) { - // If two or more parameters share the same name, they are sorted by their value - // Ref: Spec: 9.1.1 (1) - // June 12th, 2010 - changed to sort because of issue 164 by hidetaka - sort($value, SORT_STRING); - foreach ($value as $duplicate_value) { - $pairs[] = $parameter.'='.$duplicate_value; - } - } else { - $pairs[] = $parameter.'='.$value; - } - } - // For each parameter, the name is separated from the corresponding value by an '=' character (ASCII code 61) - // Each name-value pair is separated by an '&' character (ASCII code 38) - return implode('&', $pairs); - } -} diff --git a/modules/oauth/templates/registry.edit.tpl.php b/modules/oauth/templates/registry.edit.tpl.php deleted file mode 100644 index b43c40d39c3239424a148bff6084f0aa056b2406..0000000000000000000000000000000000000000 --- a/modules/oauth/templates/registry.edit.tpl.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -$this->data['jquery'] = ['core' => true, 'ui' => true, 'css' => true]; -$this->data['head'] = '<link rel="stylesheet" type="text/css" href="/'. - $this->data['baseurlpath'].'module.php/oauth/assets/css/oauth.css" />'."\n"; -$this->data['head'] .= '<script type="text/javascript" src="/'. - $this->data['baseurlpath'].'module.php/oauth/assets/js/oauth.js"></script>'; - -$this->includeAtTemplateBase('includes/header.php'); - -echo '<h1>OAuth Client</h1>'; - -echo $this->data['form']; - -echo '<p style="float: right"><a href="registry.php">'. - 'Return to entity listing <strong>without saving...</strong></a></p>'; - -$this->includeAtTemplateBase('includes/footer.php'); diff --git a/modules/oauth/templates/registry.edit.twig b/modules/oauth/templates/registry.edit.twig deleted file mode 100644 index ad9345d731a93a397528e1c6e2c0a05d7dd940f6..0000000000000000000000000000000000000000 --- a/modules/oauth/templates/registry.edit.twig +++ /dev/null @@ -1,18 +0,0 @@ -{% set pagetitle = 'SimpleSAMLphp'|trans %} -{% extends "base.twig" %} - -{% block preload %} - <link href="{{ baseurlpath }}assets/css/oauth.css" rel="stylesheet"> -{% endblock %} - -{% block postload %} - <script src="{{ baseurlpath}}assets/js/oauth.js"></script> -{% endblock %} - -{% block content %} - <h1>OAuth Client</h1> - {{ form|raw }} - <p style="float: right"> - <a href="registry.php">Return to entity listing <strong>without saving...</strong></a> - </p> -{% endblock %} diff --git a/modules/oauth/templates/registry.list.php b/modules/oauth/templates/registry.list.php deleted file mode 100644 index 1c3b287fb696b8ced33285dbe34599ebd85426ef..0000000000000000000000000000000000000000 --- a/modules/oauth/templates/registry.list.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php -$this->data['jquery'] = ['core' => true, 'ui' => true, 'css' => true]; -$this->data['head'] = '<link rel="stylesheet" type="text/css" href="/'. - $this->data['baseurlpath'].'module.php/oauth/assets/oauth.css" />'."\n"; -$this->includeAtTemplateBase('includes/header.php'); - -echo '<h1>OAuth Client Registry</h1>'; -echo '<p>Here you can register new OAuth Clients. You are successfully logged in as '. - htmlspecialchars($this->data['userid']).'</p>'; - -echo '<h2>Your clients</h2>'; -echo '<table class="metalist" style="width: 100%">'; -$i = 0; -$rows = ['odd', 'even']; -foreach ($this->data['entries']['mine'] as $entryc) { - $entry = $entryc['value']; - $i++; - echo '<tr class="'.$rows[$i % 2].'"><td>'. - htmlspecialchars($entry['name']).'</td> <td><code>'.htmlspecialchars($entry['key']). - '</code></td><td><a href="registry.edit.php?editkey='.urlencode($entry['key']). - '">edit</a><a href="registry.php?delete='.urlencode($entry['key']).'">delete</a></td></tr>'; -} -if ($i == 0) { - echo'<tr><td colspan="3">No entries registered</td></tr>'; -} -echo '</table>'; - -echo '<p><a href="registry.edit.php">Add new client</a></p>'; - -echo '<h2>Other clients</h2>'; -echo '<table class="metalist" style="width: 100%">'; -$i = 0; -$rows = ['odd', 'even']; -foreach ($this->data['entries']['others'] as $entryc) { - $entry = $entryc['value']; - $i++; - echo '<tr class="'.$rows[$i % 2].'"><td>'. - htmlspecialchars($entry['name']).'</td><td><code>'.htmlspecialchars($entry['key']). - '</code></td><td>'.(isset($entry['owner']) ? htmlspecialchars($entry['owner']) : 'No owner'). - '</td></tr>'; -} -if ($i == 0) { - echo '<tr><td colspan="3">No entries registered</td></tr>'; -} -echo '</table>'; - -$this->includeAtTemplateBase('includes/footer.php'); diff --git a/modules/oauth/templates/registry.list.twig b/modules/oauth/templates/registry.list.twig deleted file mode 100644 index 86bc5a6792a26489a6d52ec13b65538ab764ca82..0000000000000000000000000000000000000000 --- a/modules/oauth/templates/registry.list.twig +++ /dev/null @@ -1,58 +0,0 @@ -{% set pagetitle = 'SimpleSAMLphp'|trans %} -{% extends "base.twig" %} - -{% block preload %} - <link href="{{ baseurlpath }}assets/css/oauth.css" rel="stylesheet" /> -{% endblock %} - -{% block content %} - <h1>OAuth Client Registry</h1> - <p>Here you can register new OAuth Clients. You are successfully logged in as {{ userid|escape('html') }}</p> - <h2>Your clients</h2> - - <table class="metalist" style="width: 100%;"> - {% for key, entryc in entries.mine %} - {% if loop.index0 is even %} - {% set class = 'even' %} - {% else %} - {% set class = 'odd' %} - {% endif %} - {% set entry = entryc.value %} - <tr class="{{ class }}"> - <td>{{ entry.name|escape('html') }}</td> - <td><kbd>{{ entry.key|escape('html') }}</kbd></td> - <td> - <a href="registry.edit.php?editkey={{ entry.key|escape('url') }}">edit</a> - <a href="registry.php?delete={{ entry.key|escape('url') }}">delete</a> - </td> - </tr> - {% else %} - <tr><td colspan="3">No entries registered</td></tr> - {% endfor %} - </table> - - <p><a href="registry.edit.php">Add new client</a></p> - <h2>Other clients</h2> - - <table class="metalist" style="width: 100%"> - {% for key, entryc in entries.others %} - {% if loop.index0 is even %} - {% set class = 'even' %} - {% else %} - {% set class = 'odd' %} - {% endif %} - {% set entry = entryc.value %} - <tr class="{{ class }}"> - <td>{{ entry.name|escape('html') }}</td> - <td><kbd>{{ entry.key|escape('html') }}</kbd></td> - {% if eentry.owner is defined %}} - <td>{{ entry.owner|escape('html') }}</td> - {% else %} - <td>No owner</td> - {% endif %} - </tr> - {% else %} - <tr><td colspan="3">No entries registered</td></tr> - {% endfor %} - </table> -{% endblock%} diff --git a/modules/oauth/templates/registry.saved.php b/modules/oauth/templates/registry.saved.php deleted file mode 100644 index 2e4bd27a92a916384f614e8b55fd058803e9c199..0000000000000000000000000000000000000000 --- a/modules/oauth/templates/registry.saved.php +++ /dev/null @@ -1,8 +0,0 @@ -<?php - -$this->includeAtTemplateBase('includes/header.php'); - -echo '<h1>OAuth Client saved</h1>'; -echo '<p><a href="registry.php">Go back to OAuth client listing</a></p>'; - -$this->includeAtTemplateBase('includes/footer.php'); diff --git a/modules/oauth/templates/registry.saved.twig b/modules/oauth/templates/registry.saved.twig deleted file mode 100644 index d17f8ba4774c21f82e3b53247cc023eac025a68b..0000000000000000000000000000000000000000 --- a/modules/oauth/templates/registry.saved.twig +++ /dev/null @@ -1,9 +0,0 @@ -{% set pagetitle = 'SimpleSAMLphp'|trans %} -{% extends "base.twig" %} - -{% block content %} - <h1>OAuth Client saved</h1> - <p> - <a href="registry.php">Go back to OAuth client listing</a> - </p> -{% endblock %} diff --git a/modules/oauth/www/assets/css/oauth.css b/modules/oauth/www/assets/css/oauth.css deleted file mode 100644 index 7b8ad7e92cb2d9fcf4f6f57ecaf714898bd15fa3..0000000000000000000000000000000000000000 --- a/modules/oauth/www/assets/css/oauth.css +++ /dev/null @@ -1,84 +0,0 @@ -table.formtable { - width: 100%; -} -table.formtable tr td.name { - text-align: right; - vertical-align: top; - padding-right: .6em; -} -table.formtable tr td.value { - text-align: left; - padding: 0px; -} -table.formtable tr td.header { - padding-left: 5px; - padding-top: 8px; - font-weight: bold; - font-size: 110%; -} - -table.formtable tr td input,table.formtable tr td textarea { - width: 90%; - border: 1px solid #bbb; - margin: 2px 5px; - padding: 2px 4px; -} - -table.metalist { - border: 1px solid #aaa; - border-collapse: collapse; -} -table.metalist tr td { - padding: 2px 5px; -} -table.metalist tr.even td { - background: #e5e5e5; -} - -@media all { - div#content { - margin: .4em ! important; - } - - form { - display: inline; - } - - ul.tabset_tabs { - margin: 0px; - padding: 0px; - list-style: none; - } - - ul.tabset_tabs li { - background: none; - color: #222; - display: inline-block; - padding: 10px 15px; - cursor: pointer; - } - - ul.tabset_tabs li.current { - background: #ededed; - color: #222; - } - - .tabset_content { - display: none; - background: #ededed; - padding: 15px; - } - - .tabset_content.current { - display: inherit; - } - - #graph img { - max-width: 77%; - height: auto; - } - #table img { - max-width: 77%; - height: auto; - } -} diff --git a/modules/oauth/www/assets/js/oauth.js b/modules/oauth/www/assets/js/oauth.js deleted file mode 100644 index 442c63effcc4101a5f3ca02b50fb522cb83fd229..0000000000000000000000000000000000000000 --- a/modules/oauth/www/assets/js/oauth.js +++ /dev/null @@ -1,3 +0,0 @@ -document.addEventListener('DOMContentLoaded', function () { - $("#tabdiv").tabs(); -}); diff --git a/modules/oauth/www/getUserInfo.php b/modules/oauth/www/getUserInfo.php deleted file mode 100644 index ad9f878c8b511be1eaa9c87a1ff7ac15120f7b22..0000000000000000000000000000000000000000 --- a/modules/oauth/www/getUserInfo.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -require_once(dirname(dirname(__FILE__)).'/libextinc/OAuth.php'); - -$oauthconfig = \SimpleSAML\Configuration::getConfig('module_oauth.php'); - -if (!$oauthconfig->getBoolean('getUserInfo.enable', false)) { - throw new \Exception( - 'Get user info endpoint is disabled. This endpoint can be enabled in the module_oauth.php configuration file.' - ); -} - -$store = new \SimpleSAML\Module\oauth\OAuthStore(); -$server = new \SimpleSAML\Module\oauth\OAuthServer($store); - -$hmac_method = new OAuthSignatureMethod_HMAC_SHA1(); -$plaintext_method = new OAuthSignatureMethod_PLAINTEXT(); - -$server->add_signature_method($hmac_method); -$server->add_signature_method($plaintext_method); - -$req = OAuthRequest::from_request(); -list($consumer, $token) = $server->verify_request($req); - -$data = $store->getAuthorizedData($token->key); - -echo json_encode($data); diff --git a/modules/oauth/www/registry.edit.php b/modules/oauth/www/registry.edit.php deleted file mode 100644 index a367c482050addb0af428e566bcdc40a6b1564bc..0000000000000000000000000000000000000000 --- a/modules/oauth/www/registry.edit.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php - -// Load SimpleSAMLphp, configuration and metadata -$config = \SimpleSAML\Configuration::getInstance(); -$session = \SimpleSAML\Session::getSessionFromRequest(); -$oauthconfig = \SimpleSAML\Configuration::getOptionalConfig('module_oauth.php'); - -$store = new \SimpleSAML\Module\core\Storage\SQLPermanentStorage('oauth'); - -$authsource = "admin"; // force admin to authenticate as registry maintainer -$useridattr = $oauthconfig->getValue('useridattr', 'user'); - -if ($session->isValid($authsource)) { - $attributes = $session->getAuthData($authsource, 'Attributes'); - // Check if userid exists - if (!isset($attributes[$useridattr])) { - throw new \Exception('User ID is missing'); - } - $userid = $attributes[$useridattr][0]; -} else { - $as = \SimpleSAML\Auth\Source::getById($authsource); - $as->initLogin(\SimpleSAML\Utils\HTTP::getSelfURL()); -} - -if (array_key_exists('editkey', $_REQUEST)) { - $entryc = $store->get('consumers', $_REQUEST['editkey'], ''); - $entry = $entryc['value']; - \SimpleSAML\Module\oauth\Registry::requireOwnership($entry, $userid); -} else { - $entry = [ - 'owner' => $userid, - 'key' => \SimpleSAML\Utils\Random::generateID(), - 'secret' => \SimpleSAML\Utils\Random::generateID(), - ]; -} - -$editor = new \SimpleSAML\Module\oauth\Registry(); - -if (isset($_POST['submit'])) { - $editor->checkForm($_POST); - - $entry = $editor->formToMeta($_POST, [], ['owner' => $userid]); - - \SimpleSAML\Module\oauth\Registry::requireOwnership($entry, $userid); - - $store->set('consumers', $entry['key'], '', $entry); - - $template = new \SimpleSAML\XHTML\Template($config, 'oauth:registry.saved.php'); - $template->data['entry'] = $entry; - $template->show(); - exit; -} - -$form = $editor->metaToForm($entry); - -$template = new \SimpleSAML\XHTML\Template($config, 'oauth:registry.edit.tpl.php'); -$template->data['form'] = $form; -$template->data['jquery'] = ['core' => false, 'ui' => true, 'css' => true]; -$template->show(); diff --git a/modules/oauth/www/registry.php b/modules/oauth/www/registry.php deleted file mode 100644 index 4431835a63786095977605465fdb10254b097940..0000000000000000000000000000000000000000 --- a/modules/oauth/www/registry.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php -// Load SimpleSAMLphp, configuration and metadata -$config = \SimpleSAML\Configuration::getInstance(); -$session = \SimpleSAML\Session::getSessionFromRequest(); -$oauthconfig = \SimpleSAML\Configuration::getOptionalConfig('module_oauth.php'); - -$store = new \SimpleSAML\Module\core\Storage\SQLPermanentStorage('oauth'); - -$authsource = "admin"; // force admin to authenticate as registry maintainer -$useridattr = $oauthconfig->getValue('useridattr', 'user'); - -if ($session->isValid($authsource)) { - $attributes = $session->getAuthData($authsource, 'Attributes'); - // Check if userid exists - if (!isset($attributes[$useridattr])) { - throw new \Exception('User ID is missing'); - } - $userid = $attributes[$useridattr][0]; -} else { - $as = \SimpleSAML\Auth\Source::getById($authsource); - $as->initLogin(\SimpleSAML\Utils\HTTP::getSelfURL()); -} - -if (isset($_REQUEST['delete'])) { - $entryc = $store->get('consumers', $_REQUEST['delete'], ''); - $entry = $entryc['value']; - - \SimpleSAML\Module\oauth\Registry::requireOwnership($entry, $userid); - $store->remove('consumers', $entry['key'], ''); -} - -$list = $store->getList('consumers'); - -$slist = ['mine' => [], 'others' => []]; -if (is_array($list)) { - foreach ($list as $listitem) { - if (array_key_exists('owner', $listitem['value'])) { - if ($listitem['value']['owner'] === $userid) { - $slist['mine'][] = $listitem; - continue; - } - } - } - $slist['others'][] = $listitem; -} - -$template = new \SimpleSAML\XHTML\Template($config, 'oauth:registry.list.php'); -$template->data['entries'] = $slist; -$template->data['userid'] = $userid; -$template->show();