mirror of
https://github.com/friendica/friendica
synced 2024-11-18 21:03:41 +00:00
Enable remote authentication with HTTP Signatures
This commit is contained in:
parent
d23e877b21
commit
0aab620d32
4 changed files with 66 additions and 28 deletions
|
@ -12,7 +12,9 @@ use Friendica\Core\Config\Cache\ConfigCacheLoader;
|
||||||
use Friendica\Core\Config\Cache\IConfigCache;
|
use Friendica\Core\Config\Cache\IConfigCache;
|
||||||
use Friendica\Core\Config\Configuration;
|
use Friendica\Core\Config\Configuration;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
|
use Friendica\Model\Profile;
|
||||||
use Friendica\Network\HTTPException\InternalServerErrorException;
|
use Friendica\Network\HTTPException\InternalServerErrorException;
|
||||||
|
use Friendica\Util\HTTPSignature;
|
||||||
use Friendica\Util\Profiler;
|
use Friendica\Util\Profiler;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
@ -1143,6 +1145,13 @@ class App
|
||||||
Core\Worker::executeIfIdle();
|
Core\Worker::executeIfIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->getMode()->isNormal()) {
|
||||||
|
$requester = HTTPSignature::getSigner('', $_SERVER);
|
||||||
|
if (!empty($requester)) {
|
||||||
|
Profile::addVisitorCookieForHandle($requester);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ZRL
|
// ZRL
|
||||||
if (!empty($_GET['zrl']) && $this->getMode()->isNormal()) {
|
if (!empty($_GET['zrl']) && $this->getMode()->isNormal()) {
|
||||||
$this->query_string = Model\Profile::stripZrls($this->query_string);
|
$this->query_string = Model\Profile::stripZrls($this->query_string);
|
||||||
|
|
|
@ -1083,34 +1083,18 @@ class Profile
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OpenWebAuth authentication.
|
* Set the visitor cookies (see remote_user()) for the given handle
|
||||||
*
|
*
|
||||||
* Ported from Hubzilla: https://framagit.org/hubzilla/core/blob/master/include/zid.php
|
* @param string $handle Visitor handle
|
||||||
*
|
* @return array Visitor contact array
|
||||||
* @param string $token
|
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
|
||||||
* @throws \ImagickException
|
|
||||||
*/
|
*/
|
||||||
public static function openWebAuthInit($token)
|
public static function addVisitorCookieForHandle($handle)
|
||||||
{
|
{
|
||||||
$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.
|
// Try to find the public contact entry of the visitor.
|
||||||
$cid = Contact::getIdForURL($visitor_handle);
|
$cid = Contact::getIdForURL($handle);
|
||||||
if(!$cid) {
|
if (!$cid) {
|
||||||
Logger::log('owt: unable to finger ' . $visitor_handle, Logger::DEBUG);
|
Logger::log('unable to finger ' . $handle, Logger::DEBUG);
|
||||||
return;
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$visitor = DBA::selectFirst('contact', [], ['id' => $cid]);
|
$visitor = DBA::selectFirst('contact', [], ['id' => $cid]);
|
||||||
|
@ -1133,6 +1117,43 @@ class Profile
|
||||||
|
|
||||||
$_SESSION['remote'][] = ['cid' => $contact['id'], 'uid' => $contact['uid'], 'url' => $visitor['url']];
|
$_SESSION['remote'][] = ['cid' => $contact['id'], 'uid' => $contact['uid'], 'url' => $visitor['url']];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$a->contact = $visitor;
|
||||||
|
|
||||||
|
Logger::info('Authenticated visitor', ['url' => $visitor['url']]);
|
||||||
|
|
||||||
|
return $visitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenWebAuth authentication.
|
||||||
|
*
|
||||||
|
* Ported from Hubzilla: https://framagit.org/hubzilla/core/blob/master/include/zid.php
|
||||||
|
*
|
||||||
|
* @param string $token
|
||||||
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
|
* @throws \ImagickException
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
$visitor = self::addVisitorCookieForHandle($visitor_handle);
|
||||||
|
if (empty($visitor)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$arr = [
|
$arr = [
|
||||||
'visitor' => $visitor,
|
'visitor' => $visitor,
|
||||||
'url' => $a->query_string
|
'url' => $a->query_string
|
||||||
|
|
|
@ -45,9 +45,6 @@ class Photo extends BaseModule
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @todo Add Authentication to enable fetching of non public content
|
|
||||||
// $requester = HTTPSignature::getSigner('', $_SERVER);
|
|
||||||
|
|
||||||
$customsize = 0;
|
$customsize = 0;
|
||||||
$photo = false;
|
$photo = false;
|
||||||
switch($a->argc) {
|
switch($a->argc) {
|
||||||
|
|
|
@ -488,8 +488,10 @@ class HTTPSignature
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$hasGoodSignedContent = false;
|
||||||
|
|
||||||
// Check the digest when it is part of the signed data
|
// Check the digest when it is part of the signed data
|
||||||
if (in_array('digest', $sig_block['headers'])) {
|
if (!empty($content) && in_array('digest', $sig_block['headers'])) {
|
||||||
$digest = explode('=', $headers['digest'], 2);
|
$digest = explode('=', $headers['digest'], 2);
|
||||||
if ($digest[0] === 'SHA-256') {
|
if ($digest[0] === 'SHA-256') {
|
||||||
$hashalg = 'sha256';
|
$hashalg = 'sha256';
|
||||||
|
@ -503,6 +505,8 @@ class HTTPSignature
|
||||||
if (!empty($hashalg) && base64_encode(hash($hashalg, $content, true)) != $digest[1]) {
|
if (!empty($hashalg) && base64_encode(hash($hashalg, $content, true)) != $digest[1]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$hasGoodSignedContent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the signed date field is in an acceptable range
|
// Check if the signed date field is in an acceptable range
|
||||||
|
@ -512,6 +516,7 @@ class HTTPSignature
|
||||||
Logger::log("Header date '" . $headers['date'] . "' is with " . $diff . " seconds out of the 300 second frame. The signature is invalid.");
|
Logger::log("Header date '" . $headers['date'] . "' is with " . $diff . " seconds out of the 300 second frame. The signature is invalid.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
$hasGoodSignedContent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the content-length when it is part of the signed data
|
// Check the content-length when it is part of the signed data
|
||||||
|
@ -521,6 +526,12 @@ class HTTPSignature
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that the authentication had been done with some content
|
||||||
|
// Without this check someone could authenticate with fakeable data
|
||||||
|
if (!$hasGoodSignedContent) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return $key['url'];
|
return $key['url'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue