From 0d48cb959fc4927ac63587f57b71252a956db61e Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 3 Aug 2018 19:32:51 +0200 Subject: [PATCH 1/9] Add XMLreader in PHP requirements --- install/INSTALL.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/install/INSTALL.txt b/install/INSTALL.txt index c39c8ad8b..3671d95ac 100644 --- a/install/INSTALL.txt +++ b/install/INSTALL.txt @@ -89,9 +89,10 @@ web server platforms. php.ini file - and with no hosting provider restrictions on the use of exec() and proc_open(). - - curl, gd (with at least jpeg and png support), mysqli, mbstring, xml, zip - and openssl extensions. The imagick extension MAY be used instead of gd, - but is not required and MAY also be disabled via configuration option. + - curl, gd (with at least jpeg and png support), mysqli, mbstring, xml, + xmlreader, zip and openssl extensions. The imagick extension MAY be used + instead of gd, but is not required and MAY also be disabled via + configuration option. - some form of email server or email gateway such that PHP mail() works. From 5c30b2f27133d4fe20e509f095951e1fb36e77ba Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 8 Aug 2018 09:10:03 +0200 Subject: [PATCH 2/9] update install.txt --- install/INSTALL.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/INSTALL.txt b/install/INSTALL.txt index 3671d95ac..421656023 100644 --- a/install/INSTALL.txt +++ b/install/INSTALL.txt @@ -90,7 +90,7 @@ web server platforms. exec() and proc_open(). - curl, gd (with at least jpeg and png support), mysqli, mbstring, xml, - xmlreader, zip and openssl extensions. The imagick extension MAY be used + xmlreader (FreeBSD), zip and openssl extensions. The imagick extension MAY be used instead of gd, but is not required and MAY also be disabled via configuration option. From 054c5da294b5254cde2b0ff3dabff713c5eedb46 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 9 Aug 2018 15:47:57 +0200 Subject: [PATCH 3/9] search form action for channel search needs the channel address --- include/nav.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/nav.php b/include/nav.php index 05d2d199f..56fe9b901 100644 --- a/include/nav.php +++ b/include/nav.php @@ -175,7 +175,7 @@ function nav($template = 'default') { $search_form_action = 'network'; break; case 'channel': - $search_form_action = 'channel'; + $search_form_action = 'channel/' . App::$profile['channel_address']; break; default: $search_form_action = 'search'; From b3d1ea4cd5d4ba3fd951b23e536fc2681c12f957 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 9 Aug 2018 17:03:20 +0200 Subject: [PATCH 4/9] fix zid leaking to nonzot sites if markdown is enabled --- include/markdown.php | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/include/markdown.php b/include/markdown.php index de9862801..18ccbd411 100644 --- a/include/markdown.php +++ b/include/markdown.php @@ -74,8 +74,11 @@ function markdown_to_bb($s, $use_zrl = false, $options = []) { // Convert everything that looks like a link to a link if($use_zrl) { - $s = str_replace(['[img', '/img]'], ['[zmg', '/zmg]'], $s); - $s = preg_replace("/([^\]\=\{]|^)(https?\:\/\/)([a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)/ismu", '$1[zrl=$2$3]$2$3[/zrl]',$s); + if (strpos($s,'[/img]') !== false) { + $s = preg_replace_callback("/\[img\](.*?)\[\/img\]/ism", 'use_zrl_cb_img', $s); + $s = preg_replace_callback("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", 'use_zrl_cb_img_x', $s); + } + $s = preg_replace_callback("/([^\]\=\{]|^)(https?\:\/\/)([a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)/ismu", 'use_zrl_cb_link',$s); } else { $s = preg_replace("/([^\]\=\{]|^)(https?\:\/\/)([a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)/ismu", '$1[url=$2$3]$2$3[/url]',$s); @@ -85,7 +88,7 @@ function markdown_to_bb($s, $use_zrl = false, $options = []) { $s = preg_replace("/(\[code\])+(.*?)(\[\/code\])+/ism","[code]$2[/code]", $s); // Don't show link to full picture (until it is fixed) - $s = scale_external_images($s, false); + //$s = scale_external_images($s, false); /** * @hooks markdown_to_bb @@ -96,6 +99,41 @@ function markdown_to_bb($s, $use_zrl = false, $options = []) { return $s; } +function use_zrl_cb_link($match) { + $res = ''; + $is_zid = is_matrix_url(trim($match[0])); + + if($is_zid) + $res = $match[1] . '[zrl=' . $match[2] . $match[3] . ']' . $match[2] . $match[3] . '[/zrl]'; + else + $res = $match[1] . '[url=' . $match[2] . $match[3] . ']' . $match[2] . $match[3] . '[/url]'; + + return $res; +} + +function use_zrl_cb_img($match) { + $res = ''; + $is_zid = is_matrix_url(trim($match[1])); + + if($is_zid) + $res = '[zmg]' . $match[1] . '[/zmg]'; + else + $res = $match[0]; + + return $res; +} + +function use_zrl_cb_img_x($match) { + $res = ''; + $is_zid = is_matrix_url(trim($match[3])); + + if($is_zid) + $res = '[zmg=' . $match[1] . 'x' . $match[2] . ']' . $match[3] . '[/zmg]'; + else + $res = $match[0]; + + return $res; +} /** * @brief From 7890157f52378ec7a643e76e3b5c88fa23795d32 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 9 Aug 2018 23:07:50 +0200 Subject: [PATCH 5/9] revert debug comment from the last commit --- include/markdown.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/markdown.php b/include/markdown.php index 18ccbd411..058b79909 100644 --- a/include/markdown.php +++ b/include/markdown.php @@ -88,7 +88,7 @@ function markdown_to_bb($s, $use_zrl = false, $options = []) { $s = preg_replace("/(\[code\])+(.*?)(\[\/code\])+/ism","[code]$2[/code]", $s); // Don't show link to full picture (until it is fixed) - //$s = scale_external_images($s, false); + $s = scale_external_images($s, false); /** * @hooks markdown_to_bb From d3362dfa0c7e1cbd76342e83c480effc1b8765f8 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 10 Aug 2018 16:56:22 +0200 Subject: [PATCH 6/9] Add translation for missed string --- Zotlabs/Module/Admin/Site.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zotlabs/Module/Admin/Site.php b/Zotlabs/Module/Admin/Site.php index 292de4c3a..5912a7c97 100644 --- a/Zotlabs/Module/Admin/Site.php +++ b/Zotlabs/Module/Admin/Site.php @@ -332,7 +332,7 @@ class Site { '$register_policy' => array('register_policy', t("Does this site allow new member registration?"), get_config('system','register_policy'), "", $register_choices), '$invite_only' => array('invite_only', t("Invitation only"), get_config('system','invitation_only'), t("Only allow new member registrations with an invitation code. Above register policy must be set to Yes.")), '$minimum_age' => array('minimum_age', t("Minimum age"), (x(get_config('system','minimum_age'))?get_config('system','minimum_age'):13), t("Minimum age (in years) for who may register on this site.")), - '$access_policy' => array('access_policy', t("Which best describes the types of account offered by this hub?"), get_config('system','access_policy'), "This is displayed on the public server site list.", $access_choices), + '$access_policy' => array('access_policy', t("Which best describes the types of account offered by this hub?"), get_config('system','access_policy'), t("This is displayed on the public server site list."), $access_choices), '$register_text' => array('register_text', t("Register text"), htmlspecialchars(get_config('system','register_text'), ENT_QUOTES, 'UTF-8'), t("Will be displayed prominently on the registration page.")), '$role' => $role, '$frontpage' => array('frontpage', t("Site homepage to show visitors (default: login box)"), get_config('system','frontpage'), t("example: 'public' to show public stream, 'page/sys/home' to show a system webpage called 'home' or 'include:home.html' to include a file.")), From 0b31c677f253907ee9a36e12ae51763b2d69a574 Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Thu, 9 Aug 2018 22:35:12 -0400 Subject: [PATCH 7/9] Fixes to OAuth2 connect-with-openid. Add zothash Claim. Add zotwebbie Claim. --- Zotlabs/Identity/OAuth2Server.php | 5 +-- Zotlabs/Identity/OAuth2Storage.php | 51 ++++++++++++++++++++++++++++-- Zotlabs/Module/Authorize.php | 12 ++++--- Zotlabs/Module/Token.php | 8 ++--- Zotlabs/Module/Userinfo.php | 17 ++++++++++ 5 files changed, 81 insertions(+), 12 deletions(-) create mode 100644 Zotlabs/Module/Userinfo.php diff --git a/Zotlabs/Identity/OAuth2Server.php b/Zotlabs/Identity/OAuth2Server.php index cbb4748fe..b747b95db 100644 --- a/Zotlabs/Identity/OAuth2Server.php +++ b/Zotlabs/Identity/OAuth2Server.php @@ -4,7 +4,7 @@ namespace Zotlabs\Identity; class OAuth2Server extends \OAuth2\Server { - public function __construct(OAuth2Storage $storage, $config = []) { + public function __construct(OAuth2Storage $storage, $config = null) { if(! is_array($config)) { $config = [ @@ -19,7 +19,8 @@ class OAuth2Server extends \OAuth2\Server { $this->addGrantType(new \OAuth2\GrantType\ClientCredentials($storage)); // Add the "Authorization Code" grant type (this is where the oauth magic happens) - $this->addGrantType(new \OAuth2\GrantType\AuthorizationCode($storage)); + // Need to use OpenID\GrantType to return id_token (see:https://github.com/bshaffer/oauth2-server-php/issues/443) + $this->addGrantType(new \OAuth2\OpenID\GrantType\AuthorizationCode($storage)); $keyStorage = new \OAuth2\Storage\Memory( [ 'keys' => [ diff --git a/Zotlabs/Identity/OAuth2Storage.php b/Zotlabs/Identity/OAuth2Storage.php index bc6db565c..a50b21a70 100644 --- a/Zotlabs/Identity/OAuth2Storage.php +++ b/Zotlabs/Identity/OAuth2Storage.php @@ -50,20 +50,67 @@ class OAuth2Storage extends \OAuth2\Storage\Pdo { public function getUser($username) { - $x = channelx_by_nick($username); + $x = channelx_by_n($username); if(! $x) { return false; } return( [ + 'webbie' => $x['channel_address'].'@'.\App::get_hostname(), + 'zothash' => $x['channel_hash'], 'username' => $x['channel_address'], 'user_id' => $x['channel_id'], + 'name' => $x['channel_name'], 'firstName' => $x['channel_name'], 'lastName' => '', 'password' => 'NotARealPassword' ] ); } + public function scopeExists($scope) { + // Report that the scope is valid even if it's not. + // We will only return a very small subset no matter what. + // @TODO: Truly validate the scope + // see vendor/bshaffer/oauth2-server-php/src/OAuth2/Storage/ScopeInterface.php and + // vendor/bshaffer/oauth2-server-php/src/OAuth2/Storage/Pdo.php + // for more info. + return true; + } + + public function getDefaultScope($client_id=null) { + // Do not REQUIRE a scope + // see vendor/bshaffer/oauth2-server-php/src/OAuth2/Storage/ScopeInterface.php and + // for more info. + return null; + } + + public function getUserClaims ($user_id, $claims) { + // Populate the CLAIMS requested (if any). + // @TODO: create a more reasonable/comprehensive list. + // @TODO: present claims on the AUTHORIZATION screen + + $userClaims = Array(); + $claims = explode (' ', trim($claims)); + $validclaims = Array ("name","preferred_username","zothash"); + $claimsmap = Array ( + "zotwebbie" => 'webbie', + "zothash" => 'zothash', + "name" => 'name', + "preferred_username" => "username" + ); + $userinfo = $this->getUser($user_id); + foreach ($validclaims as $validclaim) { + if (in_array($validclaim,$claims)) { + $claimkey = $claimsmap[$validclaim]; + $userClaims[$validclaim] = $userinfo[$claimkey]; + } else { + $userClaims[$validclaim] = $validclaim; + } + } + $userClaims["sub"]=$user_id; + return $userClaims; + } + /** * plaintext passwords are bad! Override this for your application * @@ -78,4 +125,4 @@ class OAuth2Storage extends \OAuth2\Storage\Pdo { return true; } -} \ No newline at end of file +} diff --git a/Zotlabs/Module/Authorize.php b/Zotlabs/Module/Authorize.php index bfb76150f..e042848d8 100644 --- a/Zotlabs/Module/Authorize.php +++ b/Zotlabs/Module/Authorize.php @@ -60,12 +60,16 @@ class Authorize extends \Zotlabs\Web\Controller { $request = \OAuth2\Request::createFromGlobals(); $response = new \OAuth2\Response(); + // Note, "sub" field must match type and content. $user_id is used to populate - make sure it's a string. + $channel = channelx_by_n(local_channel()); + $user_id = $channel["channel_id"]; + // If the client is not registered, add to the database if (!$client = $storage->getClientDetails($client_id)) { - $client_secret = random_string(16); + // Until "Dynamic Client Registration" is pursued - allow new clients to assign their own secret in the REQUEST + $client_secret = (isset($_REQUEST["client_secret"])) ? $_REQUEST["client_secret"] : random_string(16); // Client apps are registered per channel - $user_id = local_channel(); - $storage->setClientDetails($client_id, $client_secret, $redirect_uri, 'authorization_code', null, $user_id); + $storage->setClientDetails($client_id, $client_secret, $redirect_uri, 'authorization_code', urldecode($_REQUEST["scope"]), $user_id); } if (!$client = $storage->getClientDetails($client_id)) { @@ -83,7 +87,7 @@ class Authorize extends \Zotlabs\Web\Controller { // print the authorization code if the user has authorized your client $is_authorized = ($_POST['authorize'] === 'allow'); - $s->handleAuthorizeRequest($request, $response, $is_authorized, local_channel()); + $s->handleAuthorizeRequest($request, $response, $is_authorized, $user_id); if ($is_authorized) { $code = substr($response->getHttpHeader('Location'), strpos($response->getHttpHeader('Location'), 'code=') + 5, 40); logger('Authorization Code: ' . $code); diff --git a/Zotlabs/Module/Token.php b/Zotlabs/Module/Token.php index 32cf95c61..2bd33c761 100644 --- a/Zotlabs/Module/Token.php +++ b/Zotlabs/Module/Token.php @@ -27,11 +27,11 @@ class Token extends \Zotlabs\Web\Controller { $_SERVER['PHP_AUTH_PW'] = $password; } } - - $s = new \Zotlabs\Identity\OAuth2Server(new OAuth2Storage(\DBA::$dba->db)); + $storage = new OAuth2Storage(\DBA::$dba->db); + $s = new \Zotlabs\Identity\OAuth2Server($storage); $request = \OAuth2\Request::createFromGlobals(); - $s->handleTokenRequest($request)->send(); - + $response = $s->handleTokenRequest($request); + $response->send(); killme(); } diff --git a/Zotlabs/Module/Userinfo.php b/Zotlabs/Module/Userinfo.php new file mode 100644 index 000000000..6c881f078 --- /dev/null +++ b/Zotlabs/Module/Userinfo.php @@ -0,0 +1,17 @@ +db)); + $request = \OAuth2\Request::createFromGlobals(); + $s->handleUserInfoRequest($request)->send(); + killme(); + } + +} From e587fe5ce84ed5c248287eb55c6ae193ebd3222b Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Fri, 10 Aug 2018 12:44:57 -0400 Subject: [PATCH 8/9] Add user_id = local_channel() to the where clause of updates --- Zotlabs/Module/Settings/Oauth2.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Zotlabs/Module/Settings/Oauth2.php b/Zotlabs/Module/Settings/Oauth2.php index 985095115..52da20598 100644 --- a/Zotlabs/Module/Settings/Oauth2.php +++ b/Zotlabs/Module/Settings/Oauth2.php @@ -45,14 +45,15 @@ class Oauth2 { grant_types = '%s', scope = '%s', user_id = %d - WHERE client_id='%s'", + WHERE client_id='%s' and user_id = %s", dbesc($name), dbesc($secret), dbesc($redirect), dbesc($grant), dbesc($scope), intval(local_channel()), - dbesc($name)); + dbesc($name), + intval(local_channel())); } else { $r = q("INSERT INTO oauth_clients (client_id, client_secret, redirect_uri, grant_types, scope, user_id) VALUES ('%s','%s','%s','%s','%s',%d)", From af042ccf07b00af70b5e7844747dde9a263c697c Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Fri, 10 Aug 2018 13:51:45 -0400 Subject: [PATCH 9/9] OAuth2 UI and settings updates --- Zotlabs/Module/Settings/Oauth2.php | 30 ++++++++++++++++++++++++++---- view/tpl/settings_oauth2.tpl | 7 ++++--- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/Zotlabs/Module/Settings/Oauth2.php b/Zotlabs/Module/Settings/Oauth2.php index 52da20598..91abd1de3 100644 --- a/Zotlabs/Module/Settings/Oauth2.php +++ b/Zotlabs/Module/Settings/Oauth2.php @@ -10,10 +10,19 @@ class Oauth2 { if(x($_POST,'remove')){ check_form_security_token_redirectOnErr('/settings/oauth2', 'settings_oauth2'); - + $name = ((x($_POST,'name')) ? escape_tags(trim($_POST['name'])) : ''); + logger("REMOVE! ".$name." uid: ".local_channel()); $key = $_POST['remove']; - q("DELETE FROM tokens WHERE id='%s' AND uid=%d", - dbesc($key), + q("DELETE FROM oauth_authorization_codes WHERE client_id='%s' AND user_id=%d", + dbesc($name), + intval(local_channel()) + ); + q("DELETE FROM oauth_access_tokens WHERE client_id='%s' AND user_id=%d", + dbesc($name), + intval(local_channel()) + ); + q("DELETE FROM oauth_refresh_tokens WHERE client_id='%s' AND user_id=%d", + dbesc($name), intval(local_channel()) ); goaway(z_root()."/settings/oauth2/"); @@ -129,6 +138,18 @@ class Oauth2 { dbesc(argv(3)), intval(local_channel()) ); + $r = q("DELETE FROM oauth_access_tokens WHERE client_id = '%s' AND user_id = %d", + dbesc(argv(3)), + intval(local_channel()) + ); + $r = q("DELETE FROM oauth_authorization_codes WHERE client_id = '%s' AND user_id = %d", + dbesc(argv(3)), + intval(local_channel()) + ); + $r = q("DELETE FROM oauth_refresh_tokens WHERE client_id = '%s' AND user_id = %d", + dbesc(argv(3)), + intval(local_channel()) + ); goaway(z_root()."/settings/oauth2/"); return; } @@ -136,7 +157,8 @@ class Oauth2 { $r = q("SELECT oauth_clients.*, oauth_access_tokens.access_token as oauth_token, (oauth_clients.user_id = %d) AS my FROM oauth_clients - LEFT JOIN oauth_access_tokens ON oauth_clients.client_id=oauth_access_tokens.client_id + LEFT JOIN oauth_access_tokens ON oauth_clients.client_id=oauth_access_tokens.client_id AND + oauth_clients.user_id=oauth_access_tokens.user_id WHERE oauth_clients.user_id IN (%d,0)", intval(local_channel()), intval(local_channel()) diff --git a/view/tpl/settings_oauth2.tpl b/view/tpl/settings_oauth2.tpl index 882d34ea9..f3bf59a12 100755 --- a/view/tpl/settings_oauth2.tpl +++ b/view/tpl/settings_oauth2.tpl @@ -4,8 +4,6 @@
-
- {{foreach $apps as $app}} + + +
{{if $app.client_id}}

{{$app.client_id}}

{{else}}

{{$noname}}

{{/if}} {{if $app.my}} @@ -28,8 +29,8 @@ {{/if}}
+
{{/foreach}} -