Merge branch 'dev' of https://framagit.org/hubzilla/core into xdev_merge

This commit is contained in:
zotlabs 2018-08-12 15:10:19 -07:00
commit 2d29095348
11 changed files with 160 additions and 28 deletions

View File

@ -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' => [

View File

@ -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;
}
}
}

View File

@ -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.")),

View File

@ -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);

View File

@ -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/");
@ -45,14 +54,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)",
@ -128,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;
}
@ -135,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())

View File

@ -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();
}

View File

@ -0,0 +1,17 @@
<?php
namespace Zotlabs\Module;
use Zotlabs\Identity\OAuth2Storage;
class Userinfo extends \Zotlabs\Web\Controller {
function init() {
$s = new \Zotlabs\Identity\OAuth2Server(new OAuth2Storage(\DBA::$dba->db));
$request = \OAuth2\Request::createFromGlobals();
$s->handleUserInfoRequest($request)->send();
killme();
}
}

View File

@ -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);
@ -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

View File

@ -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';

View File

@ -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 (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.
- some form of email server or email gateway such that PHP mail() works.

View File

@ -4,8 +4,6 @@
</div>
<div class="section-content-tools-wrapper">
<form action="settings/oauth2" method="post" autocomplete="off">
<input type='hidden' name='form_security_token' value='{{$form_security_token}}'>
<div id="profile-edit-links">
<ul>
@ -16,6 +14,9 @@
</div>
{{foreach $apps as $app}}
<form action="settings/oauth2" method="post" autocomplete="off">
<input type='hidden' name='form_security_token' value='{{$form_security_token}}'>
<input type='hidden' name='name' value='{{$app.client_id}}'>
<div class='oauthapp'>
{{if $app.client_id}}<h4>{{$app.client_id}}</h4>{{else}}<h4>{{$noname}}</h4>{{/if}}
{{if $app.my}}
@ -28,8 +29,8 @@
<a href="{{$baseurl}}/settings/oauth2/delete/{{$app.client_id}}?t={{$form_security_token}}" title="{{$delete}}"><i class="fa fa-trash-o btn btn-outline-secondary"></i></a>
{{/if}}
</div>
</form>
{{/foreach}}
</form>
</div>
</div>