mirror of
https://github.com/friendica/friendica
synced 2025-04-27 00:30:10 +00:00
Merge pull request #5253 from rabuzarus/20180616_-_magic_auth_test_2
Port hubzillas OpenWebAuth - remote authentification
This commit is contained in:
commit
a5550b4702
15 changed files with 1196 additions and 50 deletions
73
src/Model/OpenWebAuthToken.php
Normal file
73
src/Model/OpenWebAuthToken.php
Normal file
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file src/Model/OpenWebAuthToken.php
|
||||
*/
|
||||
namespace Friendica\Model;
|
||||
|
||||
use Friendica\Database\DBM;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use dba;
|
||||
|
||||
/**
|
||||
* Methods to deal with entries of the 'openwebauth-token' table.
|
||||
*/
|
||||
class OpenWebAuthToken
|
||||
{
|
||||
/**
|
||||
* Create an entry in the 'openwebauth-token' table.
|
||||
*
|
||||
* @param string $type Verify type.
|
||||
* @param int $uid The user ID.
|
||||
* @param string $token
|
||||
* @param string $meta
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function create($type, $uid, $token, $meta)
|
||||
{
|
||||
$fields = [
|
||||
"type" => $type,
|
||||
"uid" => $uid,
|
||||
"token" => $token,
|
||||
"meta" => $meta,
|
||||
"created" => DateTimeFormat::utcNow()
|
||||
];
|
||||
return dba::insert("openwebauth-token", $fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "meta" field of an entry in the openwebauth-token table.
|
||||
*
|
||||
* @param string $type Verify type.
|
||||
* @param int $uid The user ID.
|
||||
* @param string $token
|
||||
*
|
||||
* @return string|boolean The meta enry or false if not found.
|
||||
*/
|
||||
public static function getMeta($type, $uid, $token)
|
||||
{
|
||||
$condition = ["type" => $type, "uid" => $uid, "token" => $token];
|
||||
|
||||
$entry = dba::selectFirst("openwebauth-token", ["id", "meta"], $condition);
|
||||
if (DBM::is_result($entry)) {
|
||||
dba::delete("openwebauth-token", ["id" => $entry["id"]]);
|
||||
|
||||
return $entry["meta"];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Purge entries of a verify-type older than interval.
|
||||
*
|
||||
* @param string $type Verify type.
|
||||
* @param string $interval SQL compatible time interval
|
||||
*/
|
||||
public static function purge($type, $interval)
|
||||
{
|
||||
$condition = ["`type` = ? AND `created` < ?", $type, DateTimeFormat::utcNow() . " - INTERVAL " . $interval];
|
||||
dba::delete("openwebauth-token", $condition);
|
||||
}
|
||||
|
||||
}
|
|
@ -17,6 +17,7 @@ use Friendica\Core\System;
|
|||
use Friendica\Core\Worker;
|
||||
use Friendica\Database\DBM;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\OpenWebAuthToken;
|
||||
use Friendica\Protocol\Diaspora;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\Network;
|
||||
|
@ -978,27 +979,128 @@ class Profile
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the 'zrl' parameter and initiate the remote authentication.
|
||||
*
|
||||
* This method checks if the visitor has a public contact entry and
|
||||
* redirects the visitor to his/her instance to start the magic auth (Authentication)
|
||||
* process.
|
||||
*
|
||||
* Ported from Hubzilla: https://framagit.org/hubzilla/core/blob/master/include/channel.php
|
||||
*
|
||||
* @param App $a Application instance.
|
||||
*/
|
||||
public static function zrlInit(App $a)
|
||||
{
|
||||
$my_url = self::getMyURL();
|
||||
$my_url = Network::isUrlValid($my_url);
|
||||
|
||||
if ($my_url) {
|
||||
// Is it a DDoS attempt?
|
||||
// The check fetches the cached value from gprobe to reduce the load for this system
|
||||
$urlparts = parse_url($my_url);
|
||||
if (!local_user()) {
|
||||
// Is it a DDoS attempt?
|
||||
// The check fetches the cached value from gprobe to reduce the load for this system
|
||||
$urlparts = parse_url($my_url);
|
||||
|
||||
$result = Cache::get('gprobe:' . $urlparts['host']);
|
||||
if ((!is_null($result)) && (in_array($result['network'], [NETWORK_FEED, NETWORK_PHANTOM]))) {
|
||||
logger('DDoS attempt detected for ' . $urlparts['host'] . ' by ' . $_SERVER['REMOTE_ADDR'] . '. server data: ' . print_r($_SERVER, true), LOGGER_DEBUG);
|
||||
return;
|
||||
$result = Cache::get('gprobe:' . $urlparts['host']);
|
||||
if ((!is_null($result)) && (in_array($result['network'], [NETWORK_FEED, NETWORK_PHANTOM]))) {
|
||||
logger('DDoS attempt detected for ' . $urlparts['host'] . ' by ' . $_SERVER['REMOTE_ADDR'] . '. server data: ' . print_r($_SERVER, true), LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
Worker::add(PRIORITY_LOW, 'GProbe', $my_url);
|
||||
$arr = ['zrl' => $my_url, 'url' => $a->cmd];
|
||||
Addon::callHooks('zrl_init', $arr);
|
||||
|
||||
// Try to find the public contact entry of the visitor.
|
||||
$cid = Contact::getIdForURL($my_url);
|
||||
if (!$cid) {
|
||||
logger('No contact record found for ' . $my_url, LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
$contact = dba::selectFirst('contact',['id', 'url'], ['id' => $cid]);
|
||||
|
||||
if (DBM::is_result($contact) && remote_user() && remote_user() === $contact['id']) {
|
||||
// The visitor is already authenticated.
|
||||
return;
|
||||
}
|
||||
|
||||
logger('Not authenticated. Invoking reverse magic-auth for ' . $my_url, LOGGER_DEBUG);
|
||||
|
||||
// Try to avoid recursion - but send them home to do a proper magic auth.
|
||||
$query = str_replace(array('?zrl=', '&zid='), array('?rzrl=', '&rzrl='), $a->query_string);
|
||||
// The other instance needs to know where to redirect.
|
||||
$dest = urlencode(System::baseUrl() . '/' . $query);
|
||||
|
||||
// We need to extract the basebath from the profile url
|
||||
// to redirect the visitors '/magic' module.
|
||||
// Note: We should have the basepath of a contact also in the contact table.
|
||||
$urlarr = explode('/profile/', $contact['url']);
|
||||
$basepath = $urlarr[0];
|
||||
|
||||
if ($basepath != System::baseUrl() && !strstr($dest, '/magic') && !strstr($dest, '/rmagic')) {
|
||||
goaway($basepath . '/magic' . '?f=&owa=1&dest=' . $dest);
|
||||
}
|
||||
}
|
||||
|
||||
Worker::add(PRIORITY_LOW, 'GProbe', $my_url);
|
||||
$arr = ['zrl' => $my_url, 'url' => $a->cmd];
|
||||
Addon::callHooks('zrl_init', $arr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* OpenWebAuth authentication.
|
||||
*
|
||||
* Ported from Hubzilla: https://framagit.org/hubzilla/core/blob/master/include/zid.php
|
||||
*
|
||||
* @param string $token
|
||||
*/
|
||||
public static function openWebAuthInit($token)
|
||||
{
|
||||
$a = get_app();
|
||||
|
||||
// Clean old OpenWebAuthToken entries.
|
||||
OpenWebAuthToken::purge('owt', '3 MINUTE');
|
||||
|
||||
// Check if the token we got is the same one
|
||||
// we have stored in the database.
|
||||
$visitor_handle = OpenWebAuthToken::getMeta('owt', 0, $token);
|
||||
|
||||
if($visitor_handle === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to find the public contact entry of the visitor.
|
||||
$cid = Contact::getIdForURL($visitor_handle);
|
||||
if(!$cid) {
|
||||
logger('owt: unable to finger ' . $visitor_handle, LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
$visitor = dba::selectFirst('contact', [], ['id' => $cid]);
|
||||
|
||||
// Authenticate the visitor.
|
||||
$_SESSION['authenticated'] = 1;
|
||||
$_SESSION['visitor_id'] = $visitor['id'];
|
||||
$_SESSION['visitor_handle'] = $visitor['addr'];
|
||||
$_SESSION['visitor_home'] = $visitor['url'];
|
||||
|
||||
$arr = [
|
||||
'visitor' => $visitor,
|
||||
'url' => $a->query_string
|
||||
];
|
||||
/**
|
||||
* @hooks magic_auth_success
|
||||
* Called when a magic-auth was successful.
|
||||
* * \e array \b visitor
|
||||
* * \e string \b url
|
||||
*/
|
||||
Addon::callHooks('magic_auth_success', $arr);
|
||||
|
||||
$a->contact = $arr['visitor'];
|
||||
|
||||
info(L10n::t('OpenWebAuth: %1$s welcomes %2$s', $a->get_hostname(), $visitor['name']));
|
||||
|
||||
logger('OpenWebAuth: auth success from ' . $visitor['addr'], LOGGER_DEBUG);
|
||||
}
|
||||
|
||||
public static function zrl($s, $force = false)
|
||||
{
|
||||
if (!strlen($s)) {
|
||||
|
@ -1042,4 +1144,26 @@ class Profile
|
|||
|
||||
return $uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stip zrl parameter from a string.
|
||||
*
|
||||
* @param string $s The input string.
|
||||
* @return string The zrl.
|
||||
*/
|
||||
public static function stripZrls($s)
|
||||
{
|
||||
return preg_replace('/[\?&]zrl=(.*?)([\?&]|$)/is', '', $s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stip query parameter from a string.
|
||||
*
|
||||
* @param string $s The input string.
|
||||
* @return string The query parameter.
|
||||
*/
|
||||
public static function stripQueryParam($s, $param)
|
||||
{
|
||||
return preg_replace('/[\?&]' . $param . '=(.*?)(&|$)/ism', '$2', $s);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue