diff --git a/modules/oauth/config-template/module_oauth.php b/modules/oauth/config-template/module_oauth.php index 41b46d5bbca70239df914227abdbc29110e1f9d9..1fceb519be28271148a45b2df4bfdf060c9a8e15 100644 --- a/modules/oauth/config-template/module_oauth.php +++ b/modules/oauth/config-template/module_oauth.php @@ -5,24 +5,20 @@ */ $config = array ( + /* 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, - /* 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 + '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', - // 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', - + // 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/hooks/hook_cron.php b/modules/oauth/hooks/hook_cron.php index 182c51a692285b0035d338bcb3a83c5927c73c4a..9d99fad2a3ac608cb297bbe54dbe531e86cceaaa 100644 --- a/modules/oauth/hooks/hook_cron.php +++ b/modules/oauth/hooks/hook_cron.php @@ -4,26 +4,28 @@ * * @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)); +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 sspmod_core_Storage_SQLPermanentStorage('oauth'); - $cleaned = $store->removeExpired(); - -# if ($cleaned > 0) - $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; - } + $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 sspmod_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 index 583ef5d6c06061ffb0caff4cf552cbb6b818118c..2339b3b0c26833852838cbd58bb7f9e2c746f74d 100644 --- a/modules/oauth/hooks/hook_frontpage.php +++ b/modules/oauth/hooks/hook_frontpage.php @@ -4,14 +4,14 @@ * * @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'] = array( - 'href' => SimpleSAML\Module::getModuleURL('oauth/registry.php'), - 'text' => array('en' => 'OAuth Consumer Registry'), - 'shorttext' => array('en' => 'OAuth Registry'), - ); +function oauth_hook_frontpage(&$links) +{ + assert(is_array($links)); + assert(array_key_exists('links', $links)); + $links['federation']['oauthregistry'] = array( + 'href' => SimpleSAML\Module::getModuleURL('oauth/registry.php'), + 'text' => array('en' => 'OAuth Consumer Registry'), + 'shorttext' => array('en' => 'OAuth Registry'), + ); } diff --git a/modules/oauth/lib/Consumer.php b/modules/oauth/lib/Consumer.php index 4a8f48b975ff3a565338d8be97d65635b685f7ef..8456c85fe6ea585d08c20c0cc0bad7448ad1161c 100644 --- a/modules/oauth/lib/Consumer.php +++ b/modules/oauth/lib/Consumer.php @@ -8,158 +8,168 @@ require_once(dirname(dirname(__FILE__)) . '/libextinc/OAuth.php'); * @author Andreas Ă…kre Solberg, <andreas.solberg@uninett.no>, UNINETT AS. * @package SimpleSAMLphp */ -class sspmod_oauth_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 file_get_contents - * 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 = '') { - $response = @file_get_contents($url); - - if ($response === FALSE) { - $statuscode = 'unknown'; - if (preg_match('/^HTTP.*\s([0-9]{3})/', $http_response_header[0], $matches)) $statuscode = $matches[1]; - - $error = $context . ' [statuscode: ' . $statuscode . ']: '; - $contenttype = self::getContentType($http_response_header); - $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 = array('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); - - $response_acc = file_get_contents($acc_req->to_url()); - if ($response_acc === FALSE) { - 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 = array( - 'ssl' => array( - 'verify_peer' => FALSE, - 'capture_peer_cert' => TRUE, - 'capture_peer_chain' => TRUE, - ), - 'http' => array( - 'method' => 'POST', - 'content' => $postdata, - 'header' => 'Content-Type: application/x-www-form-urlencoded', - ), - ); - $context = stream_context_create($opts); - $response = file_get_contents($url, FALSE, $context); - if ($response === FALSE) { - 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); - - if (is_array($opts)) { - $opts = stream_context_create($opts); - } - $data = file_get_contents($data_req->to_url(), FALSE, $opts); - - $dataDecoded = json_decode($data, TRUE); - return $dataDecoded; - } - -} +class sspmod_oauth_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 file_get_contents + * 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 = '') + { + $response = @file_get_contents($url); + + if ($response === false) { + $statuscode = 'unknown'; + if (preg_match('/^HTTP.*\s([0-9]{3})/', $http_response_header[0], $matches)) { + $statuscode = $matches[1]; + } + + $error = $context . ' [statuscode: ' . $statuscode . ']: '; + $contenttype = self::getContentType($http_response_header); + $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 = array('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); + + $response_acc = file_get_contents($acc_req->to_url()); + if ($response_acc === false) { + 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 = array( + 'ssl' => array( + 'verify_peer' => false, + 'capture_peer_cert' => true, + 'capture_peer_chain' => true, + ), + 'http' => array( + 'method' => 'POST', + 'content' => $postdata, + 'header' => 'Content-Type: application/x-www-form-urlencoded', + ), + ); + $context = stream_context_create($opts); + $response = file_get_contents($url, false, $context); + if ($response === false) { + 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); + + if (is_array($opts)) { + $opts = stream_context_create($opts); + } + $data = file_get_contents($data_req->to_url(), false, $opts); + + $dataDecoded = json_decode($data, true); + return $dataDecoded; + } +} diff --git a/modules/oauth/lib/OAuthServer.php b/modules/oauth/lib/OAuthServer.php index 03d04fe30e355052acbc863b4b707d3f656424de..c812ac38710e70fbaa1c58887d0a58fe3d22b90e 100644 --- a/modules/oauth/lib/OAuthServer.php +++ b/modules/oauth/lib/OAuthServer.php @@ -8,9 +8,11 @@ require_once(dirname(dirname(__FILE__)) . '/libextinc/OAuth.php'); * @author Andreas Ă…kre Solberg, <andreas.solberg@uninett.no>, UNINETT AS. * @package SimpleSAMLphp */ -class sspmod_oauth_OAuthServer extends OAuthServer { - public function get_signature_methods() { - return $this->signature_methods; - } +class sspmod_oauth_OAuthServer extends OAuthServer +{ + public function get_signature_methods() + { + return $this->signature_methods; + } } diff --git a/modules/oauth/lib/OAuthStore.php b/modules/oauth/lib/OAuthStore.php index 9243a341c82f6a6642f67caa6c69efc28687dbc7..70823b116e19e89bc8842e59699838a8a54eb6fc 100644 --- a/modules/oauth/lib/OAuthStore.php +++ b/modules/oauth/lib/OAuthStore.php @@ -11,154 +11,174 @@ require_once(dirname(dirname(__FILE__)) . '/libextinc/OAuth.php'); * @author Mark Dobrinic, <mdobrinic@cozmanova.com>, Cozmanova bv * @package SimpleSAMLphp */ -class sspmod_oauth_OAuthStore extends OAuthDataStore { - - private $store; - private $config; - private $defaultversion = '1.0'; - - protected $_store_tables = array( - '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 = accestoken', - 'request' => 'requestToken.key+consumerKey = requesttoken', - ); - - function __construct() { - $this->store = new sspmod_core_Storage_SQLPermanentStorage('oauth'); - $this->config = SimpleSAML_Configuration::getOptionalConfig('module_oauth.php'); +class sspmod_oauth_OAuthStore extends OAuthDataStore +{ + private $store; + private $config; + private $defaultversion = '1.0'; + + protected $_store_tables = array( + '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 = accestoken', + 'request' => 'requestToken.key+consumerKey = requesttoken', + ); + + function __construct() + { + $this->store = new sspmod_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 $requestTokenKey RequestToken that was authorized * @param $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; - $verifier = ''; - $version = $this->defaultversion; - - // 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 version to work with - $v = $request_attributes['value']['version']; - if ($v) $version = $v; - - // 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, array("oauth_verifier"=>$verifier)); - - $this->store->set('authorized', $requestTokenKey, $verifier, $data, $this->config->getValue('requestTokenDuration', 60*30) ); - - return array($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 $requestToken - * @param $verifier - * @return unknown_type - */ - 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', 60*60*24)); - } - - 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 authorize($requestTokenKey, $data) + { + $url = null; + $verifier = ''; + $version = $this->defaultversion; + + // 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 version to work with + $v = $request_attributes['value']['version']; + if ($v) { + $version = $v; + } + + // 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, array("oauth_verifier"=>$verifier)); + + $this->store->set('authorized', $requestTokenKey, $verifier, $data, $this->config->getValue('requestTokenDuration', 60*30)); + + return array($url, $verifier); } - 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']; + /** + * 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 $requestToken + * @param $verifier + * @return unknown_type + */ + public function isAuthorized($requestToken, $verifier = '') + { + SimpleSAML\Logger::info('OAuth isAuthorized(' . $requestToken . ')'); + return $this->store->exists('authorized', $requestToken, $verifier); } - 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', 60*60*24*14)); - return FALSE; + public function getAuthorizedData($token, $verifier = '') + { + SimpleSAML\Logger::info('OAuth getAuthorizedData(' . $token . ')'); + $data = $this->store->get('authorized', $token, $verifier); + return $data['value']; } - function new_request_token($consumer, $callback = null, $version = null) { - SimpleSAML\Logger::info('OAuth new_request_token(' . $consumer . ')'); - - $lifetime = $this->config->getValue('requestTokenDuration', 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 = array( - '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); - + 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', 60*60*24)); + } + + 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); + } + } + + 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']; + } + + 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', 60*60*24*14)); + return false; + } + + function new_request_token($consumer, $callback = null, $version = null) + { + SimpleSAML\Logger::info('OAuth new_request_token(' . $consumer . ')'); + + $lifetime = $this->config->getValue('requestTokenDuration', 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 = array( + '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; } - function new_access_token($requestToken, $consumer, $verifier = null) { - SimpleSAML\Logger::info('OAuth new_access_token(' . $requestToken . ',' . $consumer . ')'); - $accestoken = new OAuthToken(SimpleSAML\Utils\Random::generateID(), SimpleSAML\Utils\Random::generateID()); - $this->store->set('access', $accestoken->key, $consumer->key, $accestoken, $this->config->getValue('accessTokenDuration', 60*60*24) ); + function new_access_token($requestToken, $consumer, $verifier = null) + { + SimpleSAML\Logger::info('OAuth new_access_token(' . $requestToken . ',' . $consumer . ')'); + $accestoken = new OAuthToken(SimpleSAML\Utils\Random::generateID(), SimpleSAML\Utils\Random::generateID()); + $this->store->set('access', $accestoken->key, $consumer->key, $accestoken, $this->config->getValue('accessTokenDuration', 60*60*24) ); return $accestoken; } @@ -168,19 +188,18 @@ class sspmod_oauth_OAuthStore extends OAuthDataStore { * @return unknown_type */ 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']; - } - - + 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 index ab2a1f09baa321fd00f5f6606dfee0eb2e1cd1ef..ee78438c4a4d6aee342305d6b681eaa9ae94c50f 100644 --- a/modules/oauth/lib/Registry.php +++ b/modules/oauth/lib/Registry.php @@ -6,127 +6,127 @@ * @author Andreas Ă…kre Solberg <andreas@uninett.no>, UNINETT AS. * @package SimpleSAMLphp */ -class sspmod_oauth_Registry { +class sspmod_oauth_Registry +{ + protected function getStandardField($request, &$entry, $key) + { + if (array_key_exists('field_' . $key, $request)) { + $entry[$key] = $request['field_' . $key]; + } else { + if (isset($entry[$key])) { + unset($entry[$key]); + } + } + } + public function formToMeta($request, $entry = array(), $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'); - protected function getStandardField($request, &$entry, $key) { - if (array_key_exists('field_' . $key, $request)) { - $entry[$key] = $request['field_' . $key]; - } else { - if (isset($entry[$key])) unset($entry[$key]); - } - } + if ($override) { + foreach ($override as $key => $value) { + $entry[$key] = $value; + } + } + return $entry; + } - public function formToMeta($request, $entry = array(), $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'); + 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.'); + } - 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'); - } + 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 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 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 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>'; - - } - } + protected function hiddenField($key, $value) + { + return '<input type="hidden" name="' . $key . '" value="' . htmlspecialchars($value) . '" />'; + } - 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 descrition</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>'; - } - -} + 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/OAuth.php b/modules/oauth/libextinc/OAuth.php index 24e68382a90e9a1b6747c806e2ce8fe5c9d94dd0..97b3905807b5ffbb28e8a5a10f4244c9df5e90ab 100644 --- a/modules/oauth/libextinc/OAuth.php +++ b/modules/oauth/libextinc/OAuth.php @@ -12,29 +12,34 @@ if (!class_exists('OAuthException')) { /* * Generic exception class */ - class OAuthException extends Exception { + class OAuthException extends Exception + { // pass } } if (!class_exists('OAuthConsumer')) { - class OAuthConsumer { + class OAuthConsumer + { public $key; public $secret; - function __construct($key, $secret, $callback_url=NULL) { + function __construct($key, $secret, $callback_url = null) + { $this->key = $key; $this->secret = $secret; $this->callback_url = $callback_url; } - function __toString() { + function __toString() + { return "OAuthConsumer[key=$this->key,secret=$this->secret]"; } } } -class OAuthToken { +class OAuthToken +{ // access tokens and request tokens public $key; public $secret; @@ -43,7 +48,8 @@ class OAuthToken { * key = the token * secret = the token secret */ - function __construct($key, $secret) { + function __construct($key, $secret) + { $this->key = $key; $this->secret = $secret; } @@ -52,7 +58,8 @@ class OAuthToken { * generates the basic string serialization of a token that a server * would respond to request_token and access_token calls with */ - function to_string() { + function to_string() + { return "oauth_token=" . OAuthUtil::urlencode_rfc3986($this->key) . "&oauth_token_secret=" . @@ -60,7 +67,8 @@ class OAuthToken { "&oauth_callback_confirmed=true"; } - function __toString() { + function __toString() + { return $this->to_string(); } } @@ -69,7 +77,8 @@ class OAuthToken { * A class for implementing a Signature Method * See section 9 ("Signing Requests") in the spec */ -abstract class OAuthSignatureMethod { +abstract class OAuthSignatureMethod +{ /** * Needs to return the name of the Signature Method (ie HMAC-SHA1) * @return string @@ -96,7 +105,8 @@ abstract class OAuthSignatureMethod { * @param string $signature * @return bool */ - public function check_signature($request, $consumer, $token, $signature) { + public function check_signature($request, $consumer, $token, $signature) + { $built = $this->build_signature($request, $consumer, $token); // Check for zero length, although unlikely here @@ -125,12 +135,15 @@ abstract class OAuthSignatureMethod { * character (ASCII code 38) even if empty. * - Chapter 9.2 ("HMAC-SHA1") */ -class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod { - function get_name() { +class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod +{ + function get_name() + { return "HMAC-SHA1"; } - public function build_signature($request, $consumer, $token) { + public function build_signature($request, $consumer, $token) + { $base_string = $request->get_signature_base_string(); $request->base_string = $base_string; @@ -151,8 +164,10 @@ class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod { * 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() { +class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod +{ + public function get_name() + { return "PLAINTEXT"; } @@ -165,7 +180,8 @@ class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod { * Please note that the second encoding MUST NOT happen in the SignatureMethod, as * OAuthRequest handles this! */ - public function build_signature($request, $consumer, $token) { + public function build_signature($request, $consumer, $token) + { $key_parts = array( $consumer->secret, ($token) ? $token->secret : "" @@ -187,8 +203,10 @@ class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod { * specification. * - Chapter 9.3 ("RSA-SHA1") */ -abstract class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod { - public function get_name() { +abstract class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod +{ + public function get_name() + { return "RSA-SHA1"; } @@ -206,7 +224,8 @@ abstract class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod { // Either way should return a string representation of the certificate protected abstract function fetch_private_cert(&$request); - public function build_signature($request, $consumer, $token) { + public function build_signature($request, $consumer, $token) + { $base_string = $request->get_signature_base_string(); $request->base_string = $base_string; @@ -225,7 +244,8 @@ abstract class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod { return base64_encode($signature); } - public function check_signature($request, $consumer, $token, $signature) { + public function check_signature($request, $consumer, $token, $signature) + { $decoded_sig = base64_decode($signature); $base_string = $request->get_signature_base_string(); @@ -246,7 +266,8 @@ abstract class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod { } } -class OAuthRequest { +class OAuthRequest +{ protected $parameters; protected $http_method; protected $http_url; @@ -255,7 +276,8 @@ class OAuthRequest { public static $version = '1.0'; public static $POST_INPUT = 'php://input'; - function __construct($http_method, $http_url, $parameters=NULL) { + function __construct($http_method, $http_url, $parameters = null) + { $parameters = ($parameters) ? $parameters : array(); $parameters = array_merge( OAuthUtil::parse_parameters(parse_url($http_url, PHP_URL_QUERY)), $parameters); $this->parameters = $parameters; @@ -267,7 +289,8 @@ class OAuthRequest { /** * 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) { + public static function from_request($http_method = null, $http_url = null, $parameters = null) + { $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") ? 'http' : 'https'; @@ -319,7 +342,8 @@ class OAuthRequest { /** * 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) { + public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters = null) + { $parameters = ($parameters) ? $parameters : array(); $defaults = array("oauth_version" => OAuthRequest::$version, "oauth_nonce" => OAuthRequest::generate_nonce(), @@ -333,7 +357,8 @@ class OAuthRequest { return new OAuthRequest($http_method, $http_url, $parameters); } - public function set_parameter($name, $value, $allow_duplicates = true) { + 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])) { @@ -348,15 +373,18 @@ class OAuthRequest { } } - public function get_parameter($name) { + public function get_parameter($name) + { return isset($this->parameters[$name]) ? $this->parameters[$name] : null; } - public function get_parameters() { + public function get_parameters() + { return $this->parameters; } - public function unset_parameter($name) { + public function unset_parameter($name) + { unset($this->parameters[$name]); } @@ -364,7 +392,8 @@ class OAuthRequest { * The request parameters, sorted and concatenated into a normalized string. * @return string */ - public function get_signable_parameters() { + public function get_signable_parameters() + { // Grab all parameters $params = $this->parameters; @@ -384,7 +413,8 @@ class OAuthRequest { * and the parameters (normalized), each urlencoded * and the concated with &. */ - public function get_signature_base_string() { + public function get_signature_base_string() + { $parts = array( $this->get_normalized_http_method(), $this->get_normalized_http_url(), @@ -399,7 +429,8 @@ class OAuthRequest { /** * just uppercases the http method */ - public function get_normalized_http_method() { + public function get_normalized_http_method() + { return strtoupper($this->http_method); } @@ -407,7 +438,8 @@ class OAuthRequest { * parses the url and rebuilds it to be * scheme://host/path */ - public function get_normalized_http_url() { + public function get_normalized_http_url() + { $parts = parse_url($this->http_url); $scheme = (isset($parts['scheme'])) ? $parts['scheme'] : 'http'; @@ -425,7 +457,8 @@ class OAuthRequest { /** * builds a url usable for a GET request */ - public function to_url() { + public function to_url() + { $post_data = $this->to_postdata(); $out = $this->get_normalized_http_url(); if ($post_data) { @@ -437,14 +470,15 @@ class OAuthRequest { /** * builds the data one would send in a POST request */ - public function to_postdata() { + public function to_postdata() + { return OAuthUtil::build_http_query($this->parameters); } /** * builds the Authorization: header */ - public function to_header($realm=null) { + public function to_header($realm = null) { $first = true; if($realm) { $out = 'Authorization: OAuth realm="' . OAuthUtil::urlencode_rfc3986($realm) . '"'; @@ -468,12 +502,14 @@ class OAuthRequest { return $out; } - public function __toString() { + public function __toString() + { return $this->to_url(); } - public function sign_request($signature_method, $consumer, $token) { + public function sign_request($signature_method, $consumer, $token) + { $this->set_parameter( "oauth_signature_method", $signature_method->get_name(), @@ -483,7 +519,8 @@ class OAuthRequest { $this->set_parameter("oauth_signature", $signature, false); } - public function build_signature($signature_method, $consumer, $token) { + public function build_signature($signature_method, $consumer, $token) + { $signature = $signature_method->build_signature($this, $consumer, $token); return $signature; } @@ -491,14 +528,16 @@ class OAuthRequest { /** * util function: current timestamp */ - private static function generate_timestamp() { + private static function generate_timestamp() + { return time(); } /** * util function: current nonce */ - private static function generate_nonce() { + private static function generate_nonce() + { $mt = microtime(); $rand = mt_rand(); @@ -506,18 +545,21 @@ class OAuthRequest { } } -class OAuthServer { +class OAuthServer +{ protected $timestamp_threshold = 300; // in seconds, five minutes - protected $version = '1.0'; // hi blaine + protected $version = '1.0'; // hi blaine protected $signature_methods = array(); protected $data_store; - function __construct($data_store) { + function __construct($data_store) + { $this->data_store = $data_store; } - public function add_signature_method($signature_method) { + public function add_signature_method($signature_method) + { $this->signature_methods[$signature_method->get_name()] = $signature_method; } @@ -528,13 +570,14 @@ class OAuthServer { * process a request_token request * returns the request token on success */ - public function fetch_request_token(&$request) { + public function fetch_request_token(&$request) + { $this->get_version($request); $consumer = $this->get_consumer($request); // no token required for the initial token request - $token = NULL; + $token = null; $this->check_signature($request, $consumer, $token); @@ -549,7 +592,8 @@ class OAuthServer { * process an access_token request * returns the access token on success */ - public function fetch_access_token(&$request) { + public function fetch_access_token(&$request) + { $this->get_version($request); $consumer = $this->get_consumer($request); @@ -569,7 +613,8 @@ class OAuthServer { /** * verify an api call, checks all the parameters */ - public function verify_request(&$request) { + public function verify_request(&$request) + { $this->get_version($request); $consumer = $this->get_consumer($request); $token = $this->get_token($request, $consumer, "access"); @@ -581,7 +626,8 @@ class OAuthServer { /** * version 1 */ - private function get_version(&$request) { + private function get_version(&$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. @@ -597,10 +643,11 @@ class OAuthServer { /** * figure out the signature with some defaults */ - private function get_signature_method($request) { + private function get_signature_method($request) + { $signature_method = $request instanceof OAuthRequest ? $request->get_parameter("oauth_signature_method") - : NULL; + : null; if (!$signature_method) { // According to chapter 7 ("Accessing Protected Ressources") the signature-method @@ -622,10 +669,11 @@ class OAuthServer { /** * try to find the consumer for the provided request's consumer key */ - private function get_consumer($request) { + private function get_consumer($request) + { $consumer_key = $request instanceof OAuthRequest ? $request->get_parameter("oauth_consumer_key") - : NULL; + : null; if (!$consumer_key) { throw new OAuthException("Invalid consumer key"); @@ -642,10 +690,11 @@ class OAuthServer { /** * try to find the token for the provided request's token key */ - private function get_token($request, $consumer, $token_type="access") { + private function get_token($request, $consumer, $token_type="access") + { $token_field = $request instanceof OAuthRequest ? $request->get_parameter('oauth_token') - : NULL; + : null; if (!empty($token_field)) { $token = $this->data_store->lookup_token( @@ -665,14 +714,15 @@ class OAuthServer { * all-in-one function to check the signature on a request * should guess the signature method appropriately */ - private function check_signature($request, $consumer, $token) { + private function check_signature($request, $consumer, $token) + { // this should probably be in a different method $timestamp = $request instanceof OAuthRequest ? $request->get_parameter('oauth_timestamp') - : NULL; + : null; $nonce = $request instanceof OAuthRequest ? $request->get_parameter('oauth_nonce') - : NULL; + : null; $this->check_timestamp($timestamp); $this->check_nonce($consumer, $token, $nonce, $timestamp); @@ -695,8 +745,9 @@ class OAuthServer { /** * check that the timestamp is new enough */ - private function check_timestamp($timestamp) { - if( ! $timestamp ) + private function check_timestamp($timestamp) + { + if(!$timestamp) throw new OAuthException( 'Missing timestamp parameter. The parameter is required' ); @@ -713,8 +764,9 @@ class OAuthServer { /** * check that the nonce is not repeated */ - private function check_nonce($consumer, $token, $nonce, $timestamp) { - if( ! $nonce ) + private function check_nonce($consumer, $token, $nonce, $timestamp) + { + if (!$nonce) throw new OAuthException( 'Missing nonce parameter. The parameter is required' ); @@ -733,24 +785,30 @@ class OAuthServer { } -class OAuthDataStore { - function lookup_consumer($consumer_key) { +class OAuthDataStore +{ + function lookup_consumer($consumer_key) + { // implement me } - function lookup_token($consumer, $token_type, $token) { + function lookup_token($consumer, $token_type, $token) + { // implement me } - function lookup_nonce($consumer, $token, $nonce, $timestamp) { + function lookup_nonce($consumer, $token, $nonce, $timestamp) + { // implement me } - function new_request_token($consumer, $callback = null) { + function new_request_token($consumer, $callback = null) + { // return a new token attached to this consumer } - function new_access_token($token, $consumer, $verifier = null) { + 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 @@ -759,8 +817,10 @@ class OAuthDataStore { } -class OAuthUtil { - public static function urlencode_rfc3986($input) { +class OAuthUtil +{ + public static function urlencode_rfc3986($input) + { if (is_array($input)) { return array_map(array('OAuthUtil', 'urlencode_rfc3986'), $input); } else if (is_scalar($input)) { @@ -778,7 +838,8 @@ class OAuthUtil { // 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) { + public static function urldecode_rfc3986($string) + { return urldecode($string); } @@ -787,7 +848,8 @@ class OAuthUtil { // 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) { + public static function split_header($header, $only_allow_oauth_parameters = true) + { $params = array(); if (preg_match_all('/('.($only_allow_oauth_parameters ? 'oauth_' : '').'[a-z_-]*)=(:?"([^"]*)"|([^,]*))/', $header, $matches)) { foreach ($matches[1] as $i => $h) { @@ -801,7 +863,8 @@ class OAuthUtil { } // helper to try to sort out headers for people who aren't running apache - public static function get_headers() { + 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 @@ -853,7 +916,8 @@ class OAuthUtil { // 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 ) { + public static function parse_parameters( $input ) + { if (!isset($input) || !$input) return array(); $pairs = explode('&', $input); @@ -882,7 +946,8 @@ class OAuthUtil { return $parsed_parameters; } - public static function build_http_query($params) { + public static function build_http_query($params) + { if (!$params) return ''; // Urlencode both keys and values diff --git a/modules/oauth/templates/registry.edit.twig b/modules/oauth/templates/registry.edit.twig index ec7d7594cfb4b642d5e31d9fbc6188c8d9f2f54a..7383dacb6944fcd206ca6d93b9bdfdd6afdadb1b 100644 --- a/modules/oauth/templates/registry.edit.twig +++ b/modules/oauth/templates/registry.edit.twig @@ -6,7 +6,11 @@ {% endblock %} {% block postload %} - <script src="{{ baseurlpath }}resources/javascript.js"></script> +<script type="text/javascript"> + $(document).ready(function() { + $("#tabdiv").tabs(); + }); +</script> {% endblock %} {% block content %} diff --git a/modules/oauth/www/getUserInfo.php b/modules/oauth/www/getUserInfo.php index 516b0654424436edbd4d9f229c621939bd524b7f..09e894f6a1475f14001bbbc147ca4e8bc033dc3e 100644 --- a/modules/oauth/www/getUserInfo.php +++ b/modules/oauth/www/getUserInfo.php @@ -4,8 +4,8 @@ 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.'); +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 sspmod_oauth_OAuthStore(); @@ -23,4 +23,3 @@ 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 index ef8e42ff43bb68eca426ccd3459f4cec0e950462..9ce47e8a255b47d2617a25f60b6d29c4c0e1b1ab 100644 --- a/modules/oauth/www/registry.edit.php +++ b/modules/oauth/www/registry.edit.php @@ -11,58 +11,57 @@ $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]; + $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()); + $as = SimpleSAML_Auth_Source::getById($authsource); + $as->initLogin(\SimpleSAML\Utils\HTTP::getSelfURL()); } -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.'); - if ($entry['owner'] !== $userid) - throw new Exception('OAuth Consumer has an owner that is not equal to your userid, hence you are not granted access.'); +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.'); + if ($entry['owner'] !== $userid) + throw new Exception('OAuth Consumer has an owner that is not equal to your userid, hence you are not granted access.'); } if (array_key_exists('editkey', $_REQUEST)) { - $entryc = $store->get('consumers', $_REQUEST['editkey'], ''); - $entry = $entryc['value']; - requireOwnership($entry, $userid); - + $entryc = $store->get('consumers', $_REQUEST['editkey'], ''); + $entry = $entryc['value']; + requireOwnership($entry, $userid); } else { - $entry = array( - 'owner' => $userid, - 'key' => SimpleSAML\Utils\Random::generateID(), - 'secret' => SimpleSAML\Utils\Random::generateID(), - ); + $entry = array( + 'owner' => $userid, + 'key' => SimpleSAML\Utils\Random::generateID(), + 'secret' => SimpleSAML\Utils\Random::generateID(), + ); } - $editor = new sspmod_oauth_Registry(); - if (isset($_POST['submit'])) { - $editor->checkForm($_POST); + $editor->checkForm($_POST); - $entry = $editor->formToMeta($_POST, array(), array('owner' => $userid)); + $entry = $editor->formToMeta($_POST, array(), array('owner' => $userid)); - requireOwnership($entry, $userid); + 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; + $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'] = array('core' => false, 'ui' => true, 'css' => true); $template->show(); - diff --git a/modules/oauth/www/registry.php b/modules/oauth/www/registry.php index 4b97e8b1b5b7c2af6e9657232ed8bddac4e624af..406b5cd0a3e98dee02180309f8a783d8801987bc 100644 --- a/modules/oauth/www/registry.php +++ b/modules/oauth/www/registry.php @@ -10,44 +10,44 @@ $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]; + $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()); + $as = SimpleSAML_Auth_Source::getById($authsource); + $as->initLogin(\SimpleSAML\Utils\HTTP::getSelfURL()); } -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.'); - if ($entry['owner'] !== $userid) - throw new Exception('OAuth Consumer has an owner that is not equal to your userid, hence you are not granted access.'); +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.'); + if ($entry['owner'] !== $userid) + throw new Exception('OAuth Consumer has an owner that is not equal to your userid, hence you are not granted access.'); } - if (isset($_REQUEST['delete'])) { - $entryc = $store->get('consumers', $_REQUEST['delete'], ''); - $entry = $entryc['value']; + $entryc = $store->get('consumers', $_REQUEST['delete'], ''); + $entry = $entryc['value']; - requireOwnership($entry, $userid); - $store->remove('consumers', $entry['key'], ''); + requireOwnership($entry, $userid); + $store->remove('consumers', $entry['key'], ''); } - $list = $store->getList('consumers'); $slist = array('mine' => array(), 'others' => array()); -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; +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'); diff --git a/modules/oauth/www/resources/javascript.js b/modules/oauth/www/resources/javascript.js deleted file mode 100644 index 77ef1b1a5e53c34054bdc7593183b7aa7e84f48c..0000000000000000000000000000000000000000 --- a/modules/oauth/www/resources/javascript.js +++ /dev/null @@ -1,13 +0,0 @@ -$(document).ready(function() { - $('ul.tabset_tabs li').click( - function() { - var tab_id = $(this).attr('data-tab'); - $('ul.tabset_tabs li').removeClass('current'); - $('.tabset_content').removeClass('current'); - - $(this).addClass('current'); - $("#"+tab_id).addClass('current'); - $("html, body").animate({ scrollTop: 0 }, "slow"); - } - ) -})