Fixed domain validation
This commit is contained in:
parent
d6e85bc39e
commit
934ae8beac
30
app/app.php
30
app/app.php
|
@ -15,7 +15,6 @@ use Appwrite\Database\Document;
|
||||||
use Appwrite\Database\Validator\Authorization;
|
use Appwrite\Database\Validator\Authorization;
|
||||||
use Appwrite\Network\Validator\Origin;
|
use Appwrite\Network\Validator\Origin;
|
||||||
|
|
||||||
Config::setParam('domain', 'localhost');
|
|
||||||
Config::setParam('domainVerification', false);
|
Config::setParam('domainVerification', false);
|
||||||
Config::setParam('cookieDomain', 'localhost');
|
Config::setParam('cookieDomain', 'localhost');
|
||||||
Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE);
|
Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE);
|
||||||
|
@ -33,8 +32,8 @@ Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE);
|
||||||
App::init(function ($utopia, $request, $response, $console, $project, $user, $locale, $webhooks, $audits, $usage, $clients) {
|
App::init(function ($utopia, $request, $response, $console, $project, $user, $locale, $webhooks, $audits, $usage, $clients) {
|
||||||
Authorization::$roles = ['*'];
|
Authorization::$roles = ['*'];
|
||||||
|
|
||||||
/** @var Utopia\Request $request */
|
/** @var Appwrite\Utopia\Request $request */
|
||||||
/** @var Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Document $console */
|
/** @var Appwrite\Database\Document $console */
|
||||||
/** @var Appwrite\Database\Document $project */
|
/** @var Appwrite\Database\Document $project */
|
||||||
/** @var Appwrite\Database\Document $user */
|
/** @var Appwrite\Database\Document $user */
|
||||||
|
@ -66,19 +65,19 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
|
||||||
'hostname' => $request->getHostname(),
|
'hostname' => $request->getHostname(),
|
||||||
], Document::SET_TYPE_APPEND);
|
], Document::SET_TYPE_APPEND);
|
||||||
|
|
||||||
$referrer = $request->getServer('HTTP_REFERER', '');
|
$referrer = $request->getReferer();
|
||||||
$origin = \parse_url($request->getServer('HTTP_ORIGIN', $referrer), PHP_URL_HOST);
|
$origin = \parse_url($request->getOrigin($referrer), PHP_URL_HOST);
|
||||||
$protocol = \parse_url($request->getServer('HTTP_ORIGIN', $referrer), PHP_URL_SCHEME);
|
$protocol = \parse_url($request->getOrigin($referrer), PHP_URL_SCHEME);
|
||||||
$port = \parse_url($request->getServer('HTTP_ORIGIN', $referrer), PHP_URL_PORT);
|
$port = \parse_url($request->getOrigin($referrer), PHP_URL_PORT);
|
||||||
|
|
||||||
$refDomain = $protocol.'://'.((\in_array($origin, $clients))
|
$refDomain = $protocol.'://'.((\in_array($origin, $clients))
|
||||||
? $origin : 'localhost') . (!empty($port) ? ':'.$port : '');
|
? $origin : 'localhost') . (!empty($port) ? ':'.$port : '');
|
||||||
|
|
||||||
$selfDomain = new Domain(Config::getParam('hostname'));
|
$selfDomain = new Domain($request->getHostname());
|
||||||
$endDomain = new Domain($origin);
|
$endDomain = new Domain($origin);
|
||||||
|
|
||||||
Config::setParam('domain', $request->getServer('HTTP_HOST', ''));
|
// var_dump('referer', $referrer);
|
||||||
|
// var_dump('origin', $origin);
|
||||||
// var_dump('port', $request->getPort());
|
// var_dump('port', $request->getPort());
|
||||||
// var_dump('hostname', $request->getHostname());
|
// var_dump('hostname', $request->getHostname());
|
||||||
// var_dump('protocol', $request->getProtocol());
|
// var_dump('protocol', $request->getProtocol());
|
||||||
|
@ -87,18 +86,21 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
|
||||||
// var_dump('-----------------');
|
// var_dump('-----------------');
|
||||||
// var_dump($request->debug());
|
// var_dump($request->debug());
|
||||||
|
|
||||||
|
var_dump($selfDomain->getRegisterable());
|
||||||
|
var_dump($endDomain->getRegisterable());
|
||||||
Config::setParam('domainVerification',
|
Config::setParam('domainVerification',
|
||||||
($selfDomain->getRegisterable() === $endDomain->getRegisterable()) &&
|
($selfDomain->getRegisterable() === $endDomain->getRegisterable()) &&
|
||||||
$endDomain->getRegisterable() !== '');
|
$endDomain->getRegisterable() !== '');
|
||||||
|
|
||||||
Config::setParam('cookieDomain', (
|
Config::setParam('cookieDomain', (
|
||||||
$request->getServer('HTTP_HOST', null) === 'localhost' ||
|
$request->getHostname() === 'localhost' ||
|
||||||
$request->getServer('HTTP_HOST', null) === 'localhost:'.$request->getPort() ||
|
$request->getHostname() === 'localhost:'.$request->getPort() ||
|
||||||
(\filter_var($request->getHostname(), FILTER_VALIDATE_IP) !== false)
|
(\filter_var($request->getHostname(), FILTER_VALIDATE_IP) !== false)
|
||||||
)
|
)
|
||||||
? null
|
? null
|
||||||
: '.'.$request->getHostname()
|
: '.'.$request->getHostname()
|
||||||
);
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Security Headers
|
* Security Headers
|
||||||
*
|
*
|
||||||
|
@ -107,7 +109,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
|
||||||
*/
|
*/
|
||||||
if (App::getEnv('_APP_OPTIONS_FORCE_HTTPS', 'disabled') === 'enabled') { // Force HTTPS
|
if (App::getEnv('_APP_OPTIONS_FORCE_HTTPS', 'disabled') === 'enabled') { // Force HTTPS
|
||||||
if($request->getProtocol() !== 'https') {
|
if($request->getProtocol() !== 'https') {
|
||||||
return $response->redirect('https://' . Config::getParam('domain').$request->getServer('REQUEST_URI'));
|
return $response->redirect('https://'.$request->getHostname().$request->getServer('REQUEST_URI'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->addHeader('Strict-Transport-Security', 'max-age='.(60 * 60 * 24 * 126)); // 126 days
|
$response->addHeader('Strict-Transport-Security', 'max-age='.(60 * 60 * 24 * 126)); // 126 days
|
||||||
|
@ -179,7 +181,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
|
||||||
$user = new Document([
|
$user = new Document([
|
||||||
'$id' => 0,
|
'$id' => 0,
|
||||||
'status' => Auth::USER_STATUS_ACTIVATED,
|
'status' => Auth::USER_STATUS_ACTIVATED,
|
||||||
'email' => 'app.'.$project->getId().'@service.'.Config::getParam('domain'),
|
'email' => 'app.'.$project->getId().'@service.'.$request->getHostname(),
|
||||||
'password' => '',
|
'password' => '',
|
||||||
'name' => $project->getAttribute('name', 'Untitled'),
|
'name' => $project->getAttribute('name', 'Untitled'),
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -160,8 +160,8 @@ App::post('/v1/account/sessions')
|
||||||
->param('email', '', function () { return new Email(); }, 'User email.')
|
->param('email', '', function () { return new Email(); }, 'User email.')
|
||||||
->param('password', '', function () { return new Password(); }, 'User password. Must be between 6 to 32 chars.')
|
->param('password', '', function () { return new Password(); }, 'User password. Must be between 6 to 32 chars.')
|
||||||
->action(function ($email, $password, $request, $response, $projectDB, $webhook, $audit) {
|
->action(function ($email, $password, $request, $response, $projectDB, $webhook, $audit) {
|
||||||
/** @var Utopia\Request $request */
|
/** @var Appwrite\Utopia\Request $request */
|
||||||
/** @var Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Database $projectDB */
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
/** @var Appwrite\Event\Event $webhook */
|
/** @var Appwrite\Event\Event $webhook */
|
||||||
/** @var Appwrite\Event\Event $audit */
|
/** @var Appwrite\Event\Event $audit */
|
||||||
|
@ -230,15 +230,15 @@ App::post('/v1/account/sessions')
|
||||||
$response
|
$response
|
||||||
->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($profile->getId(), $secret)]))
|
->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($profile->getId(), $secret)]))
|
||||||
;
|
;
|
||||||
|
|
||||||
$response->dynamic($session, Response::MODEL_SESSION);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$response
|
$response
|
||||||
->addCookie(Auth::$cookieName.'_legacy', Auth::encodeSession($profile->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null)
|
->addCookie(Auth::$cookieName.'_legacy', Auth::encodeSession($profile->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null)
|
||||||
->addCookie(Auth::$cookieName, Auth::encodeSession($profile->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite'))
|
->addCookie(Auth::$cookieName, Auth::encodeSession($profile->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite'))
|
||||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||||
->json($session->getArrayCopy(['$id', 'type', 'expire']))
|
;
|
||||||
|
|
||||||
|
$response->dynamic($session, Response::MODEL_SESSION);
|
||||||
;
|
;
|
||||||
}, ['request', 'response', 'projectDB', 'webhook', 'audit']);
|
}, ['request', 'response', 'projectDB', 'webhook', 'audit']);
|
||||||
|
|
||||||
|
@ -309,7 +309,7 @@ App::get('/v1/account/sessions/oauth2/callback/:provider/:projectId')
|
||||||
/** @var Utopia\Request $request */
|
/** @var Utopia\Request $request */
|
||||||
/** @var Utopia\Response $response */
|
/** @var Utopia\Response $response */
|
||||||
|
|
||||||
$domain = Config::getParam('domain');
|
$domain = $request->getHostname();
|
||||||
$protocol = $request->getProtocol();
|
$protocol = $request->getProtocol();
|
||||||
|
|
||||||
$response
|
$response
|
||||||
|
@ -334,7 +334,7 @@ App::post('/v1/account/sessions/oauth2/callback/:provider/:projectId')
|
||||||
/** @var Utopia\Request $request */
|
/** @var Utopia\Request $request */
|
||||||
/** @var Utopia\Response $response */
|
/** @var Utopia\Response $response */
|
||||||
|
|
||||||
$domain = Config::getParam('domain');
|
$domain = $request->getHostname();
|
||||||
$protocol = $request->getProtocol();
|
$protocol = $request->getProtocol();
|
||||||
|
|
||||||
$response
|
$response
|
||||||
|
|
|
@ -567,29 +567,18 @@ App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
|
||||||
$response
|
$response
|
||||||
->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)]))
|
->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)]))
|
||||||
;
|
;
|
||||||
|
|
||||||
$response->dynamic(new Document(\array_merge($membership->getArrayCopy(), [
|
|
||||||
'email' => $user->getAttribute('email'),
|
|
||||||
'name' => $user->getAttribute('name'),
|
|
||||||
])), Response::MODEL_MEMBERSHIP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$response
|
$response
|
||||||
->addCookie(Auth::$cookieName.'_legacy', Auth::encodeSession($user->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null)
|
->addCookie(Auth::$cookieName.'_legacy', Auth::encodeSession($user->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null)
|
||||||
->addCookie(Auth::$cookieName, Auth::encodeSession($user->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite'))
|
->addCookie(Auth::$cookieName, Auth::encodeSession($user->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite'))
|
||||||
->json(\array_merge($membership->getArrayCopy([
|
|
||||||
'$id',
|
|
||||||
'userId',
|
|
||||||
'teamId',
|
|
||||||
'roles',
|
|
||||||
'invited',
|
|
||||||
'joined',
|
|
||||||
'confirm',
|
|
||||||
]), [
|
|
||||||
'email' => $user->getAttribute('email'),
|
|
||||||
'name' => $user->getAttribute('name'),
|
|
||||||
]))
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
$response->dynamic(new Document(\array_merge($membership->getArrayCopy(), [
|
||||||
|
'email' => $user->getAttribute('email'),
|
||||||
|
'name' => $user->getAttribute('name'),
|
||||||
|
])), Response::MODEL_MEMBERSHIP);
|
||||||
|
|
||||||
}, ['request', 'response', 'user', 'projectDB', 'audit']);
|
}, ['request', 'response', 'user', 'projectDB', 'audit']);
|
||||||
|
|
||||||
App::delete('/v1/teams/:teamId/memberships/:inviteId')
|
App::delete('/v1/teams/:teamId/memberships/:inviteId')
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\View;
|
|
||||||
use Utopia\Config\Config;
|
|
||||||
|
|
||||||
App::init(function ($utopia, $request, $response, $layout) {
|
App::init(function ($utopia, $request, $response, $layout) {
|
||||||
/** @var Utopia\App $utopia */
|
/** @var Utopia\App $utopia */
|
||||||
|
@ -18,7 +16,7 @@ App::init(function ($utopia, $request, $response, $layout) {
|
||||||
$layout
|
$layout
|
||||||
->setParam('title', APP_NAME)
|
->setParam('title', APP_NAME)
|
||||||
->setParam('protocol', $request->getProtocol())
|
->setParam('protocol', $request->getProtocol())
|
||||||
->setParam('domain', Config::getParam('domain'))
|
->setParam('domain', $request->getHostname())
|
||||||
->setParam('home', App::getEnv('_APP_HOME'))
|
->setParam('home', App::getEnv('_APP_HOME'))
|
||||||
->setParam('setup', App::getEnv('_APP_SETUP'))
|
->setParam('setup', App::getEnv('_APP_SETUP'))
|
||||||
->setParam('class', 'unknown')
|
->setParam('class', 'unknown')
|
||||||
|
|
|
@ -322,7 +322,7 @@ App::get('/open-api-2.json')
|
||||||
'url' => 'https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE',
|
'url' => 'https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
'host' => \parse_url(App::getEnv('_APP_HOME', Config::getParam('domain')), PHP_URL_HOST),
|
'host' => \parse_url(App::getEnv('_APP_HOME', $request->getHostname()), PHP_URL_HOST),
|
||||||
'basePath' => '/v1',
|
'basePath' => '/v1',
|
||||||
'schemes' => ['https'],
|
'schemes' => ['https'],
|
||||||
'consumes' => ['application/json', 'multipart/form-data'],
|
'consumes' => ['application/json', 'multipart/form-data'],
|
||||||
|
@ -369,7 +369,7 @@ App::get('/open-api-2.json')
|
||||||
],
|
],
|
||||||
'externalDocs' => [
|
'externalDocs' => [
|
||||||
'description' => 'Full API docs, specs and tutorials',
|
'description' => 'Full API docs, specs and tutorials',
|
||||||
'url' => $request->getProtocol().'://'.Config::getParam('domain').'/docs',
|
'url' => $request->getProtocol().'://'.$request->getHostname().'/docs',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,7 @@ class Request extends UtopiaRequest
|
||||||
|
|
||||||
public function debug()
|
public function debug()
|
||||||
{
|
{
|
||||||
return $this->swoole->server;
|
return $this->swoole->header;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -184,11 +184,35 @@ class Request extends UtopiaRequest
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getMethod():string
|
public function getMethod(): string
|
||||||
{
|
{
|
||||||
return $this->getServer('request_method', 'UNKNOWN');
|
return $this->getServer('request_method', 'UNKNOWN');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Referer
|
||||||
|
*
|
||||||
|
* Return HTTP referer header
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getReferer(string $default = ''): string
|
||||||
|
{
|
||||||
|
return $this->getHeader('referer', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Origin
|
||||||
|
*
|
||||||
|
* Return HTTP origin header
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getOrigin(string $default = ''): string
|
||||||
|
{
|
||||||
|
return $this->getHeader('origin', $default);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get files
|
* Get files
|
||||||
*
|
*
|
||||||
|
|
|
@ -92,7 +92,7 @@ abstract class Scope extends TestCase
|
||||||
'password' => $password,
|
'password' => $password,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$session = $this->client->parseCookie($session['headers']['set-cookie'])['a_session_console'];
|
$session = $this->client->parseCookie((string)$session['headers']['set-cookie'])['a_session_console'];
|
||||||
|
|
||||||
self::$root = [
|
self::$root = [
|
||||||
'$id' => $root['body']['$id'],
|
'$id' => $root['body']['$id'],
|
||||||
|
@ -143,7 +143,7 @@ abstract class Scope extends TestCase
|
||||||
'password' => $password,
|
'password' => $password,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$session = $this->client->parseCookie($session['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']];
|
$session = $this->client->parseCookie((string)$session['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']];
|
||||||
|
|
||||||
self::$user[$this->getProject()['$id']] = [
|
self::$user[$this->getProject()['$id']] = [
|
||||||
'$id' => $user['body']['$id'],
|
'$id' => $user['body']['$id'],
|
||||||
|
|
|
@ -83,7 +83,7 @@ trait AccountBase
|
||||||
$this->assertEquals($response['headers']['status-code'], 201);
|
$this->assertEquals($response['headers']['status-code'], 201);
|
||||||
|
|
||||||
$sessionId = $response['body']['$id'];
|
$sessionId = $response['body']['$id'];
|
||||||
$session = $this->client->parseCookie($response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']];
|
$session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for FAILURE
|
* Test for FAILURE
|
||||||
|
@ -774,7 +774,7 @@ trait AccountBase
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$sessionNewId = $response['body']['$id'];
|
$sessionNewId = $response['body']['$id'];
|
||||||
$sessionNew = $this->client->parseCookie($response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']];
|
$sessionNew = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']];
|
||||||
|
|
||||||
$this->assertEquals($response['headers']['status-code'], 201);
|
$this->assertEquals($response['headers']['status-code'], 201);
|
||||||
|
|
||||||
|
@ -840,7 +840,7 @@ trait AccountBase
|
||||||
'password' => $password,
|
'password' => $password,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$sessionNew = $this->client->parseCookie($response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']];
|
$sessionNew = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']];
|
||||||
|
|
||||||
$this->assertEquals($response['headers']['status-code'], 201);
|
$this->assertEquals($response['headers']['status-code'], 201);
|
||||||
|
|
||||||
|
@ -922,7 +922,7 @@ trait AccountBase
|
||||||
'password' => $password,
|
'password' => $password,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$data['session'] = $this->client->parseCookie($response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']];
|
$data['session'] = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']];
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue