diff --git a/modules/oauth/bin/demo.php b/modules/oauth/bin/demo.php index 5391958e3c3a09502a42bdb9797e634364f72599..0c75e0e3c4dac70250ef940fb8023c7fb5082b7f 100755 --- a/modules/oauth/bin/demo.php +++ b/modules/oauth/bin/demo.php @@ -16,6 +16,9 @@ require_once($baseDir . '/lib/_autoload.php'); require_once(dirname(dirname(__FILE__)) . '/libextinc/OAuth.php'); +// Needed in order to make session_start to be called before output is printed. +$session = SimpleSAML_Session::getInstance(); + $baseurl = (isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : 'https://foodle.feide.no/simplesaml'); $key = (isset($_SERVER['argv'][2]) ? $_SERVER['argv'][2] : 'key'); $secret = (isset($_SERVER['argv'][3]) ? $_SERVER['argv'][3] : 'secret'); diff --git a/modules/oauth/config-template/module_oauth.php b/modules/oauth/config-template/module_oauth.php index a1a9c10b822a9ff01fed957a3aed13f1497404d7..2d725d460a1bad197e164c2fa61166481eaf735f 100644 --- a/modules/oauth/config-template/module_oauth.php +++ b/modules/oauth/config-template/module_oauth.php @@ -10,7 +10,15 @@ $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' => FALSE, + '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', ); diff --git a/modules/oauth/hooks/hook_cron.php b/modules/oauth/hooks/hook_cron.php new file mode 100644 index 0000000000000000000000000000000000000000..60483082be77cf52a626ed425eb72995ae76d741 --- /dev/null +++ b/modules/oauth/hooks/hook_cron.php @@ -0,0 +1,30 @@ +<?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 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; + } +} +?> \ No newline at end of file diff --git a/modules/oauth/hooks/hook_frontpage.php b/modules/oauth/hooks/hook_frontpage.php new file mode 100644 index 0000000000000000000000000000000000000000..a9733b1afe85e6cf5bf9280ca6e0543288033bbd --- /dev/null +++ b/modules/oauth/hooks/hook_frontpage.php @@ -0,0 +1,18 @@ +<?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'] = array( + 'href' => SimpleSAML_Module::getModuleURL('oauth/registry.php'), + 'text' => array('en' => 'OAuth Consumer Registry'), + 'shorttext' => array('en' => 'OAuth Registry'), + ); + +} +?> \ No newline at end of file diff --git a/modules/oauth/lib/Consumer.php b/modules/oauth/lib/Consumer.php index 615bd3facd58e2e0b44122f4f08c095a95c548bb..764856b8edee0eb544baa5590ad2b004c46a8a72 100644 --- a/modules/oauth/lib/Consumer.php +++ b/modules/oauth/lib/Consumer.php @@ -35,7 +35,7 @@ class sspmod_oauth_Consumer { if(array_key_exists('error', $responseParsed)) throw new Exception('Error getting request token: ') . $responseParsed['error']; - + # echo('<pre>'); print_r($response_req); exit; $requestToken = $responseParsed['oauth_token']; @@ -66,6 +66,7 @@ class sspmod_oauth_Consumer { throw new Exception('Error contacting request_token endpoint on the OAuth Provider'); } + SimpleSAML_Logger::info(' ==== RESPONSE: '. $response_acc); parse_str($response_acc, $accessResponseParsed); diff --git a/modules/oauth/lib/OAuthStore.php b/modules/oauth/lib/OAuthStore.php index 765b93a8369a78163d0a52c9dcc75d903318f996..2471e10146708569345269dc8d0ec3b9effdf52b 100644 --- a/modules/oauth/lib/OAuthStore.php +++ b/modules/oauth/lib/OAuthStore.php @@ -11,90 +11,71 @@ require_once(dirname(dirname(__FILE__)) . '/libextinc/OAuth.php'); */ class sspmod_oauth_OAuthStore extends OAuthDataStore { - private $path; + private $store; + private $config; - function __construct($path = '/tmp/oauth/') { - - if (!file_exists($path)) { - mkdir($path); - } - if (!is_dir($path)) - throw new Exception('OAuth Storage Path [' . $path . '] is not a valid directory'); - - $this->path = $path; + function __construct() { + $this->store = new sspmod_core_Storage_SQLPermanentStorage('oauth'); + $this->config = SimpleSAML_Configuration::getOptionalConfig('module_oauth.php'); } - - private function filename($key) { - return $this->path . sha1($key) . '.oauthstore'; - } - - private function exists($key) { - return file_exists($this->filename($key)); - } - - private function get($key) { - error_log( 'Getting :' . $key . ' : ' . ($this->exists($key) ? 'FOUND' : 'NOTFOUND')); - if (!$this->exists($key)) return NULL; - return unserialize(file_get_contents($this->filename($key))); - } - - private function set($key, $value) { - error_log('Setting :' . $key . ' : ' . ($this->exists($key) ? 'FOUND' : 'NOTFOUND')); - file_put_contents($this->filename($key), serialize($value)); - } - - private function remove($key) { - unlink($this->filename($key)); - } public function authorize($requestToken, $data) { - $this->set('validated.request.' . $requestToken, $data); + # set($type, $key1, $key2, $value, $duration = NULL) { + $this->store->set('authorized', $requestToken, '', $data, $this->config->getValue('requestTokenDuration', 60*30) ); } public function isAuthorized($requestToken) { - return $this->exists('validated.request.' . $requestToken); + SimpleSAML_Logger::info('OAuth isAuthorized(' . $requestToken . ')'); + return $this->store->exists('authorized', $requestToken, ''); } public function getAuthorizedData($token) { - return $this->get('validated.request.' . $token); + SimpleSAML_Logger::info('OAuth getAuthorizedData(' . $token . ')'); + $data = $this->store->get('authorized', $token, ''); + return $data['value']; } public function moveAuthorizedData($requestToken, $accessToken) { + SimpleSAML_Logger::info('OAuth moveAuthorizedData(' . $requestToken . ', ' . $accessToken . ')'); $this->authorize($accessToken, $this->getAuthorizedData($requestToken)); - $this->remove('validated.request.' . $requestToken); + $this->store->remove('authorized', $requestToken, ''); } - private function tokenTag($tokenType = 'default', $token) { - return 'token.' . $token . '.' . $tokenType; - } - - function lookup_consumer($consumer_key) { - if ($consumer_key == 'key') return new OAuthConsumer("key", "secret", NULL); - return NULL; + 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, ''); + // SimpleSAML_Logger::info('OAuth consumer dump(' . var_export($consumer, TRUE) . ')'); + return new OAuthConsumer($consumer['value']['key'], $consumer['value']['secret'], NULL); } function lookup_token($consumer, $tokenType = 'default', $token) { - return $this->get($this->tokenTag($tokenType, $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) { - $nonceTag = 'nonce.' . $consumer->key . '.' . $nonce; - if ($this->exists($nonceTag)) - return TRUE; - - $this->set($nonceTag, $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) { + SimpleSAML_Logger::info('OAuth new_request_token(' . $consumer . ')'); $token = new OAuthToken(SimpleSAML_Utilities::generateID(), SimpleSAML_Utilities::generateID()); - $this->set($this->tokenTag('request', $token->key), $token); + $this->store->set('request', $token->key, $consumer->key, $token, $this->config->getValue('requestTokenDuration', 60*30) ); return $token; } - function new_access_token($token, $consumer) { + function new_access_token($requestToken, $consumer) { + SimpleSAML_Logger::info('OAuth new_access_token(' . $requestToken . ',' . $consumer . ')'); $token = new OAuthToken(SimpleSAML_Utilities::generateID(), SimpleSAML_Utilities::generateID()); - $this->set($this->tokenTag('access', $token->key), $token); + // SimpleSAML_Logger::info('OAuth new_access_token(' . $requestToken . ',' . $consumer . ',' . $token . ')'); + $this->store->set('access', $token->key, $consumer->key, $token, $this->config->getValue('accessTokenDuration', 60*60*24) ); return $token; } diff --git a/modules/oauth/lib/Registry.php b/modules/oauth/lib/Registry.php new file mode 100644 index 0000000000000000000000000000000000000000..06abcd426ca0707aeef404abf00408161346f04a --- /dev/null +++ b/modules/oauth/lib/Registry.php @@ -0,0 +1,144 @@ +<?php + +/** + * Editor for OAuth Client Registry + * + * @author Andreas Ă…kre Solberg <andreas@uninett.no>, UNINETT AS. + * @package simpleSAMLphp + * @version $Id$ + */ +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'); + + 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'); + } + + + 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) { + // $this->flattenLanguageField($metadata, 'name'); + // $this->flattenLanguageField($metadata, 'description'); + + return '<form action="registry.edit.php" method="post">' . + '<div id="tabdiv">' . + '<ul>' . + '<li><a href="#basic">Name and descrition</a></li>' . + // '<li><a href="#saml">SAML 2.0</a></li>' . + // '<li><a href="#attributes">Attributes</a></li>' . + // '<li><a href="#orgs">Organizations</a></li>' . + // '<li><a href="#contacts">Contacts</a></li>' . + '</ul>' . + '<div id="basic"><table class="formtable">' . + $this->standardField($metadata, 'name', 'Name of client') . + $this->standardField($metadata, 'description', 'Description of client', TRUE) . + $this->readonlyField($metadata, 'owner', 'Owner') . + $this->readonlyField($metadata, 'key', 'Consumer Key') . + $this->readonlyField($metadata, 'secret', 'Consumer Secret') . + + $this->hiddenField('field_key', $metadata['key']) . + $this->hiddenField('field_secret', $metadata['secret']) . + + '</table></div>' . + // '<div id="saml"><table class="formtable">' . + // $this->standardField($metadata, 'AssertionConsumerService', 'AssertionConsumerService endpoint') . + // $this->standardField($metadata, 'SingleLogoutService', 'SingleLogoutService endpoint') . + // // $this->standardField($metadata, 'certFingerprint', 'Certificate Fingerprint') . + // + // '</table></div>' . + '</div>' . + '<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 029166175c5f4b6ad07fac4bb47ea0502c7b95f9..cb26ed767f219ad0d37ad9205573863542ebfda2 100644 --- a/modules/oauth/libextinc/OAuth.php +++ b/modules/oauth/libextinc/OAuth.php @@ -206,7 +206,7 @@ class OAuthRequest {/*{{{*/ // next check for the auth header, we need to do some extra stuff // if that is the case, namely suck in the parameters from GET or POST // so that we can include them in the signature - if (@substr($request_headers['Authorization'], 0, 6) == "OAuth ") { + if (array_key_exists('Authorization', $request_headers) && substr($request_headers['Authorization'], 0, 6) == "OAuth ") { $header_parameters = OAuthRequest::split_header($request_headers['Authorization']); $parameters = array_merge($req_parameters, $header_parameters); $req = new OAuthRequest($http_method, $http_url, $parameters); @@ -589,6 +589,16 @@ class OAuthServer {/*{{{*/ */ private function get_token(&$request, $consumer, $token_type="access") {/*{{{*/ $token_field = @$request->get_parameter('oauth_token'); + + // SimpleSAML_Logger::info('request: ' . var_export($request, TRUE)); + // SimpleSAML_Logger::info('token_type: ' . var_export($token_type, TRUE)); + // SimpleSAML_Logger::info('token_field: ' . var_export($token_field, TRUE)); + // + // $bt = SimpleSAML_Utilities::buildBacktrace(new Exception()); + // foreach ($bt AS $t) { + // SimpleSAML_Logger::info(' ' . $t); + // } + $token = $this->data_store->lookup_token( $consumer, $token_type, $token_field ); @@ -612,7 +622,7 @@ class OAuthServer {/*{{{*/ $signature_method = $this->get_signature_method($request); - $signature = $request->get_parameter('oauth_signature'); + $signature = $request->get_parameter('oauth_signature'); $valid_sig = $signature_method->check_signature( $request, $consumer, @@ -678,74 +688,6 @@ class OAuthDataStore {/*{{{*/ }/*}}}*/ -/* A very naive dbm-based oauth storage - */ -class SimpleOAuthDataStore extends OAuthDataStore {/*{{{*/ - private $dbh; - - function __construct($path = "oauth.gdbm") {/*{{{*/ - $this->dbh = dba_popen($path, 'c', 'gdbm'); - }/*}}}*/ - - function __destruct() {/*{{{*/ - dba_close($this->dbh); - }/*}}}*/ - - function lookup_consumer($consumer_key) {/*{{{*/ - $rv = dba_fetch("consumer_$consumer_key", $this->dbh); - if ($rv === FALSE) { - return NULL; - } - $obj = unserialize($rv); - if (!($obj instanceof OAuthConsumer)) { - return NULL; - } - return $obj; - }/*}}}*/ - - function lookup_token($consumer, $token_type, $token) {/*{{{*/ - $rv = dba_fetch("${token_type}_${token}", $this->dbh); - if ($rv === FALSE) { - return NULL; - } - $obj = unserialize($rv); - if (!($obj instanceof OAuthToken)) { - return NULL; - } - return $obj; - }/*}}}*/ - - function lookup_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/ - if (dba_exists("nonce_$nonce", $this->dbh)) { - return TRUE; - } else { - dba_insert("nonce_$nonce", "1", $this->dbh); - return FALSE; - } - }/*}}}*/ - - function new_token($consumer, $type="request") {/*{{{*/ - $key = md5(time()); - $secret = time() + time(); - $token = new OAuthToken($key, md5(md5($secret))); - if (!dba_insert("${type}_$key", serialize($token), $this->dbh)) { - throw new OAuthException("doooom!"); - } - return $token; - }/*}}}*/ - - function new_request_token($consumer) {/*{{{*/ - return $this->new_token($consumer, "request"); - }/*}}}*/ - - function new_access_token($token, $consumer) {/*{{{*/ - - $token = $this->new_token($consumer, 'access'); - dba_delete("request_" . $token->key, $this->dbh); - return $token; - }/*}}}*/ -}/*}}}*/ - class OAuthUtil {/*{{{*/ public static function urlencode_rfc3986($input) {/*{{{*/ if (is_array($input)) { diff --git a/modules/oauth/templates/registry.edit.tpl.php b/modules/oauth/templates/registry.edit.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..d0841a106ea230ad44b9ec2673f8b8d60b75ed20 --- /dev/null +++ b/modules/oauth/templates/registry.edit.tpl.php @@ -0,0 +1,21 @@ +<?php + +$this->data['jquery'] = array('version' => '1.6', 'core' => TRUE, 'ui' => TRUE, 'css' => TRUE); +$this->data['head'] = '<link rel="stylesheet" type="text/css" href="/' . $this->data['baseurlpath'] . 'module.php/metaedit/resources/style.css" />' . "\n"; +$this->data['head'] .= '<script type="text/javascript"> +$(document).ready(function() { + $("#tabdiv").tabs(); +}); +</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.list.php b/modules/oauth/templates/registry.list.php new file mode 100644 index 0000000000000000000000000000000000000000..1a11da862f2e134745b200f211bc06939ac6f16e --- /dev/null +++ b/modules/oauth/templates/registry.list.php @@ -0,0 +1,57 @@ +<?php + +$this->data['jquery'] = array('version' => '1.6', 'core' => TRUE, 'ui' => TRUE, 'css' => TRUE); +$this->data['head'] = '<link rel="stylesheet" type="text/css" href="/' . $this->data['baseurlpath'] . 'module.php/oauth/resources/style.css" />' . "\n"; +// $this->data['head'] .= '<script type="text/javascript"> +// $(document).ready(function() { +// $("#tabdiv").tabs(); +// }); +// </script>'; + +$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 ' . $this->data['userid'] . '</p>'); + +echo('<h2>Your clients</h2>'); +echo('<table class="metalist" style="width: 100%">'); +$i = 0; $rows = array('odd', 'even'); +foreach($this->data['entries']['mine'] AS $entryc ) { + $entry = $entryc['value']; + $i++; + echo('<tr class="' . $rows[$i % 2] . '"> + <td>' . $entry['name'] . '</td> + <td><tt>' . $entry['key'] . '</tt></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 = array('odd', 'even'); +foreach($this->data['entries']['others'] AS $entryc ) { + $entry = $entryc['value']; + $i++; + echo('<tr class="' . $rows[$i % 2] . '"> + <td>' . $entry['name'] . '</td> + <td><tt>' . $entry['key'] . '</tt></td> + <td>' . (isset($entry['owner']) ? $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.saved.php b/modules/oauth/templates/registry.saved.php new file mode 100644 index 0000000000000000000000000000000000000000..0ff62eb50fb116c93272588995898d3b371b3299 --- /dev/null +++ b/modules/oauth/templates/registry.saved.php @@ -0,0 +1,15 @@ +<?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/www/accessToken.php b/modules/oauth/www/accessToken.php index d4de1f7f1da910d762d3015aa37de591c5d89b2f..598b916179eef87aa0348581b0f9933fc630a572 100644 --- a/modules/oauth/www/accessToken.php +++ b/modules/oauth/www/accessToken.php @@ -12,13 +12,18 @@ $server->add_signature_method($hmac_method); $server->add_signature_method($plaintext_method); $req = OAuthRequest::from_request(); + + $requestToken = $req->get_parameter('oauth_token'); + if (!$store->isAuthorized($requestToken)) { throw new Exception('Your request was not authorized. Request token [' . $requestToken . '] not found.'); } + + $accessToken = $server->fetch_access_token($req); $data = $store->moveAuthorizedData($requestToken, $accessToken->key); diff --git a/modules/oauth/www/registry.edit.php b/modules/oauth/www/registry.edit.php new file mode 100644 index 0000000000000000000000000000000000000000..b0283198d5b9b13fe45eaf9dde2aa20fc92a8100 --- /dev/null +++ b/modules/oauth/www/registry.edit.php @@ -0,0 +1,69 @@ +<?php + +/* Load simpleSAMLphp, configuration and metadata */ +$config = SimpleSAML_Configuration::getInstance(); +$session = SimpleSAML_Session::getInstance(); +$oauthconfig = SimpleSAML_Configuration::getOptionalConfig('module_oauth.php'); + +$store = new sspmod_core_Storage_SQLPermanentStorage('oauth'); + +$authsource = $oauthconfig->getValue('auth', 'admin'); +$useridattr = $oauthconfig->getValue('useridattr', 'user'); + +if ($session->isValid($authsource)) { + $attributes = $session->getAttributes(); + // Check if userid exists + if (!isset($attributes[$useridattr])) + throw new Exception('User ID is missing'); + $userid = $attributes[$useridattr][0]; +} else { + SimpleSAML_Auth_Default::initLogin($authsource, SimpleSAML_Utilities::selfURL()); +} + +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); + +} else { + $entry = array( + 'owner' => $userid, + 'key' => SimpleSAML_Utilities::generateID(), + 'secret' => SimpleSAML_Utilities::generateID(), + ); +} + + +$editor = new sspmod_oauth_Registry(); + + +if (isset($_POST['submit'])) { + $editor->checkForm($_POST); + + $entry = $editor->formToMeta($_POST, array(), array('owner' => $userid)); + + requireOwnership($entry, $userid); + +# echo('<pre>Created: '); print_r($entry); 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->show(); + diff --git a/modules/oauth/www/registry.php b/modules/oauth/www/registry.php new file mode 100644 index 0000000000000000000000000000000000000000..51bd0e8a2f6670c6d4ba2766a1be55083c561e63 --- /dev/null +++ b/modules/oauth/www/registry.php @@ -0,0 +1,58 @@ +<?php + +/* Load simpleSAMLphp, configuration and metadata */ +$config = SimpleSAML_Configuration::getInstance(); +$session = SimpleSAML_Session::getInstance(); +$oauthconfig = SimpleSAML_Configuration::getOptionalConfig('module_oauth.php'); + +$store = new sspmod_core_Storage_SQLPermanentStorage('oauth'); + +$authsource = $oauthconfig->getValue('auth', 'admin'); +$useridattr = $oauthconfig->getValue('useridattr', 'user'); + +if ($session->isValid($authsource)) { + $attributes = $session->getAttributes(); + // Check if userid exists + if (!isset($attributes[$useridattr])) + throw new Exception('User ID is missing'); + $userid = $attributes[$useridattr][0]; +} else { + SimpleSAML_Auth_Default::initLogin($authsource, SimpleSAML_Utilities::selfURL()); +} + +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']; + + 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; +} + +// echo('<pre>'); print_r($slist); exit; + +$template = new SimpleSAML_XHTML_Template($config, 'oauth:registry.list.php'); +$template->data['entries'] = $slist; +$template->data['userid'] = $userid; +$template->show(); diff --git a/modules/oauth/www/resources/style.css b/modules/oauth/www/resources/style.css new file mode 100644 index 0000000000000000000000000000000000000000..1240db06576e85af71049ead441122ca26354a04 --- /dev/null +++ b/modules/oauth/www/resources/style.css @@ -0,0 +1,37 @@ +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; +} \ No newline at end of file