New origin validator

This commit is contained in:
Eldad Fux
2020-04-14 08:44:15 +03:00
parent 984bf696b8
commit a9bfb8a7a9
6 changed files with 131 additions and 10 deletions
+9 -9
View File
@@ -16,6 +16,7 @@ use Appwrite\Database\Database;
use Appwrite\Database\Document;
use Appwrite\Database\Validator\Authorization;
use Appwrite\Event\Event;
use Appwrite\Network\Validators\Origin;
/*
* Configuration files
@@ -96,16 +97,15 @@ $utopia->init(function () use ($utopia, $request, $response, &$user, $project, $
* Adding Appwrite API domains to allow XDOMAIN communication
* Skip this check for non-web platforms which are not requiredto send an origin header
*/
$origin = parse_url($request->getServer('HTTP_ORIGIN', $request->getServer('HTTP_REFERER', '')), PHP_URL_HOST);
if (!empty($origin)
&& !in_array($origin, $clients)
&& in_array($request->getMethod(), [Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_PATCH, Request::METHOD_DELETE])
&& empty($request->getHeader('X-Appwrite-Key', ''))
) {
throw new Exception('Access from this client host is forbidden', 403);
}
$origin = $request->getServer('HTTP_ORIGIN', $request->getServer('HTTP_REFERER', ''));
$originValidator = new Origin($project->getAttribute('platforms', []));
if(!$originValidator->isValid($origin)
&& in_array($request->getMethod(), [Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_PATCH, Request::METHOD_DELETE])
&& empty($request->getHeader('X-Appwrite-Key', ''))) {
throw new Exception($originValidator->getDescription(), 403);
}
/*
* ACL Check
*/
+1 -1
View File
@@ -356,7 +356,7 @@ $utopia->get('/v1/avatars/qr')
->desc('Get QR Code')
->param('text', '', function () { return new Text(512); }, 'Plain text to be converted to QR code image.')
->param('size', 400, function () { return new Range(0, 1000); }, 'QR code size. Pass an integer between 0 to 1000. Defaults to 400.', true)
->param('margin', 1, function () { return new Range(0, 10); }, 'Margin From Edge. Pass an integer between 0 to 10. Defaults to 1.', true)
->param('margin', 1, function () { return new Range(0, 10); }, 'Margin from edge. Pass an integer between 0 to 10. Defaults to 1.', true)
->param('download', 0, function () { return new Range(0, 1); }, 'Return resulting image with \'Content-Disposition: attachment \' headers for the browser to start downloading it. Pass 0 for no header, or 1 for otherwise. Default value is set to 0.', true)
->label('scope', 'avatars.read')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 13 KiB

+121
View File
@@ -0,0 +1,121 @@
<?php
namespace Appwrite\Network\Validators;
use Utopia\Validator;
class Origin extends Validator
{
const CLIENT_TYPE_UNKNOWN = 'unknown';
const CLIENT_TYPE_WEB = 'web';
const CLIENT_TYPE_FLUTTER_IOS = 'flutter-ios';
const CLIENT_TYPE_FLUTTER_ANDROID = 'flutter-android';
const CLIENT_TYPE_FLUTTER_MACOS = 'flutter-macos';
const CLIENT_TYPE_FLUTTER_WINDOWS = 'flutter-windows';
const CLIENT_TYPE_FLUTTER_LINUX = 'flutter-linux';
const SCHEME_TYPE_HTTP = 'http';
const SCHEME_TYPE_HTTPS = 'https';
const SCHEME_TYPE_IOS = 'appwrite-ios';
const SCHEME_TYPE_ANDROID = 'appwrite-android';
const SCHEME_TYPE_MACOS = 'appwrite-macos';
const SCHEME_TYPE_WINDOWS = 'appwrite-windows';
const SCHEME_TYPE_LINUX = 'appwrite-linux';
/**
* @var array
*/
protected $platforms = [
self::SCHEME_TYPE_HTTP => 'Web',
self::SCHEME_TYPE_HTTPS => 'Web',
self::SCHEME_TYPE_IOS => 'iOS',
self::SCHEME_TYPE_ANDROID => 'Android',
self::SCHEME_TYPE_MACOS => 'macOS',
self::SCHEME_TYPE_WINDOWS => 'Windows',
self::SCHEME_TYPE_LINUX => 'Linux',
];
/**
* @var array
*/
protected $clients = [
APP_DOMAIN,
'localhost',
'appwrite.test',
];
/**
* @var string
*/
protected $client = self::CLIENT_TYPE_UNKNOWN;
/**
* @var string
*/
protected $host = '';
/**
* @param string $target
*/
public function __construct($platforms)
{
foreach($platforms as $platform) {
$type = (isset($platform['type'])) ? $platform['type'] : '';
switch ($type) {
case self::CLIENT_TYPE_WEB:
$this->clients[] = (isset($platform['hostname'])) ? $platform['hostname'] : '';
break;
case self::CLIENT_TYPE_FLUTTER_IOS:
case self::CLIENT_TYPE_FLUTTER_ANDROID:
case self::CLIENT_TYPE_FLUTTER_MACOS:
case self::CLIENT_TYPE_FLUTTER_WINDOWS:
case self::CLIENT_TYPE_FLUTTER_LINUX:
$this->clients[] = (isset($platform['key'])) ? $platform['key'] : '';
break;
default:
# code...
break;
}
}
}
public function getDescription()
{
if(!array_key_exists($this->client, $this->platforms)) {
return 'Unsupported platform';
}
return 'Inavlid Origin. Register your new client ('.$this->host.') as a new '
.$this->platforms[$this->client].' platform on your '.APP_NAME.' console';
}
/**
* Check if Origin has been whiltlisted
* for access to the API
*
* @param string $origin
*
* @return bool
*/
public function isValid($origin)
{
$scheme = parse_url($origin, PHP_URL_SCHEME);
$host = parse_url($origin, PHP_URL_HOST);
$this->host = $host;
$this->client = $scheme;
if(empty($host)) {
return true;
}
if(in_array($host, $this->clients)) {
return true;
}
return false;
}
}