feat: Adding Authentication injection for user id and secret
This commit is contained in:
parent
034814c924
commit
6f62f915d9
7 changed files with 102 additions and 50 deletions
|
@ -1 +1 @@
|
|||
Subproject commit 5169fe16d63066f64ab5013c78953aea04e24b53
|
||||
Subproject commit f483d9631d6f21e94aedb20b5c37c56fea06c23e
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use Ahc\Jwt\JWT;
|
||||
use Appwrite\Auth\Auth;
|
||||
use Appwrite\Auth\Authentication;
|
||||
use Appwrite\Auth\MFA\Challenge;
|
||||
use Appwrite\Auth\MFA\Type;
|
||||
use Appwrite\Auth\MFA\Type\TOTP;
|
||||
|
@ -399,14 +400,15 @@ Http::get('/v1/account/sessions')
|
|||
->inject('user')
|
||||
->inject('locale')
|
||||
->inject('authorization')
|
||||
->action(function (Response $response, Document $user, Locale $locale, Authorization $authorization) {
|
||||
->inject('authentication')
|
||||
->action(function (Response $response, Document $user, Locale $locale, Authorization $authorization, Authentication $authentication) {
|
||||
|
||||
$roles = $authorization->getRoles();
|
||||
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
|
||||
$isAppUser = Auth::isAppUser($roles);
|
||||
|
||||
$sessions = $user->getAttribute('sessions', []);
|
||||
$current = Auth::sessionVerify($sessions, Auth::$secret);
|
||||
$current = Auth::sessionVerify($sessions, $authentication->getSecret());
|
||||
|
||||
foreach ($sessions as $key => $session) {/** @var Document $session */
|
||||
$countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown'));
|
||||
|
@ -445,7 +447,8 @@ Http::delete('/v1/account/sessions')
|
|||
->inject('locale')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForDeletes')
|
||||
->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Delete $queueForDeletes) {
|
||||
->inject('authentication')
|
||||
->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Delete $queueForDeletes, Authentication $authentication) {
|
||||
|
||||
$protocol = $request->getProtocol();
|
||||
$sessions = $user->getAttribute('sessions', []);
|
||||
|
@ -461,7 +464,7 @@ Http::delete('/v1/account/sessions')
|
|||
->setAttribute('current', false)
|
||||
->setAttribute('countryName', $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')));
|
||||
|
||||
if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) {
|
||||
if ($session->getAttribute('secret') == Auth::hash($authentication->getSecret())) {
|
||||
$session->setAttribute('current', true);
|
||||
|
||||
// If current session delete the cookies too
|
||||
|
@ -507,7 +510,8 @@ Http::get('/v1/account/sessions/:sessionId')
|
|||
->inject('user')
|
||||
->inject('locale')
|
||||
->inject('authorization')
|
||||
->action(function (?string $sessionId, Response $response, Document $user, Locale $locale, Authorization $authorization) {
|
||||
->inject('authentication')
|
||||
->action(function (?string $sessionId, Response $response, Document $user, Locale $locale, Authorization $authorization, Authentication $authentication) {
|
||||
|
||||
$roles = $authorization->getRoles();
|
||||
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
|
||||
|
@ -515,7 +519,7 @@ Http::get('/v1/account/sessions/:sessionId')
|
|||
|
||||
$sessions = $user->getAttribute('sessions', []);
|
||||
$sessionId = ($sessionId === 'current')
|
||||
? Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret)
|
||||
? Auth::sessionVerify($user->getAttribute('sessions'), $authentication->getSecret())
|
||||
: $sessionId;
|
||||
|
||||
foreach ($sessions as $session) {/** @var Document $session */
|
||||
|
@ -523,7 +527,7 @@ Http::get('/v1/account/sessions/:sessionId')
|
|||
$countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown'));
|
||||
|
||||
$session
|
||||
->setAttribute('current', ($session->getAttribute('secret') == Auth::hash(Auth::$secret)))
|
||||
->setAttribute('current', ($session->getAttribute('secret') == Auth::hash($authentication->getSecret())))
|
||||
->setAttribute('countryName', $countryName)
|
||||
->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $session->getAttribute('secret', '') : '')
|
||||
;
|
||||
|
@ -558,11 +562,12 @@ Http::delete('/v1/account/sessions/:sessionId')
|
|||
->inject('locale')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForDeletes')
|
||||
->action(function (?string $sessionId, ?\DateTime $requestTimestamp, Request $request, Response $response, Document $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Delete $queueForDeletes) {
|
||||
->inject('authentication')
|
||||
->action(function (?string $sessionId, ?\DateTime $requestTimestamp, Request $request, Response $response, Document $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Delete $queueForDeletes, Authentication $authentication) {
|
||||
|
||||
$protocol = $request->getProtocol();
|
||||
$sessionId = ($sessionId === 'current')
|
||||
? Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret)
|
||||
? Auth::sessionVerify($user->getAttribute('sessions'), $authentication->getSecret())
|
||||
: $sessionId;
|
||||
|
||||
$sessions = $user->getAttribute('sessions', []);
|
||||
|
@ -581,7 +586,7 @@ Http::delete('/v1/account/sessions/:sessionId')
|
|||
|
||||
$session->setAttribute('current', false);
|
||||
|
||||
if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too
|
||||
if ($session->getAttribute('secret') == Auth::hash($authentication->getSecret())) { // If current session delete the cookies too
|
||||
$session
|
||||
->setAttribute('current', true)
|
||||
->setAttribute('countryName', $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')));
|
||||
|
@ -636,10 +641,11 @@ Http::patch('/v1/account/sessions/:sessionId')
|
|||
->inject('dbForProject')
|
||||
->inject('project')
|
||||
->inject('queueForEvents')
|
||||
->action(function (?string $sessionId, Response $response, Document $user, Database $dbForProject, Document $project, Event $queueForEvents) {
|
||||
->inject('authentication')
|
||||
->action(function (?string $sessionId, Response $response, Document $user, Database $dbForProject, Document $project, Event $queueForEvents, Authentication $authentication) {
|
||||
|
||||
$sessionId = ($sessionId === 'current')
|
||||
? Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret)
|
||||
? Auth::sessionVerify($user->getAttribute('sessions'), $authentication->getSecret())
|
||||
: $sessionId;
|
||||
$sessions = $user->getAttribute('sessions', []);
|
||||
|
||||
|
@ -1142,7 +1148,8 @@ Http::get('/v1/account/sessions/oauth2/:provider/redirect')
|
|||
->inject('geodb')
|
||||
->inject('queueForEvents')
|
||||
->inject('authorization')
|
||||
->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Reader $geodb, Event $queueForEvents, Authorization $authorization) use ($oauthDefaultSuccess) {
|
||||
->inject('authentication')
|
||||
->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Reader $geodb, Event $queueForEvents, Authorization $authorization, Authentication $authentication) use ($oauthDefaultSuccess) {
|
||||
$protocol = $request->getProtocol();
|
||||
$callback = $protocol . '://' . $request->getHostname() . '/v1/account/sessions/oauth2/callback/' . $provider . '/' . $project->getId();
|
||||
$defaultState = ['success' => $project->getAttribute('url', ''), 'failure' => ''];
|
||||
|
@ -1279,7 +1286,7 @@ Http::get('/v1/account/sessions/oauth2/:provider/redirect')
|
|||
}
|
||||
|
||||
$sessions = $user->getAttribute('sessions', []);
|
||||
$current = Auth::sessionVerify($sessions, Auth::$secret);
|
||||
$current = Auth::sessionVerify($sessions, $authentication->getSecret());
|
||||
|
||||
if ($current) { // Delete current session of new one.
|
||||
$currentDocument = $dbForProject->getDocument('sessions', $current);
|
||||
|
@ -2369,14 +2376,15 @@ Http::post('/v1/account/jwt')
|
|||
->inject('response')
|
||||
->inject('user')
|
||||
->inject('dbForProject')
|
||||
->action(function (Response $response, Document $user, Database $dbForProject) {
|
||||
->inject('authentication')
|
||||
->action(function (Response $response, Document $user, Database $dbForProject, Authentication $authentication) {
|
||||
|
||||
|
||||
$sessions = $user->getAttribute('sessions', []);
|
||||
$current = new Document();
|
||||
|
||||
foreach ($sessions as $session) { /** @var Utopia\Database\Document $session */
|
||||
if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too
|
||||
if ($session->getAttribute('secret') == Auth::hash($authentication->getSecret())) { // If current session delete the cookies too
|
||||
$current = $session;
|
||||
}
|
||||
}
|
||||
|
@ -4197,7 +4205,8 @@ Http::post('/v1/account/targets/push')
|
|||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('authorization')
|
||||
->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject, Authorization $authorization) {
|
||||
->inject('authentication')
|
||||
->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject, Authorization $authorization, Authentication $authentication) {
|
||||
$targetId = $targetId == 'unique()' ? ID::unique() : $targetId;
|
||||
|
||||
$provider = $authorization->skip(fn () => $dbForProject->getDocument('providers', $providerId));
|
||||
|
@ -4213,7 +4222,7 @@ Http::post('/v1/account/targets/push')
|
|||
|
||||
$device = $detector->getDevice();
|
||||
|
||||
$sessionId = Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret);
|
||||
$sessionId = Auth::sessionVerify($user->getAttribute('sessions'), $authentication->getSecret());
|
||||
$session = $dbForProject->getDocument('sessions', $sessionId);
|
||||
|
||||
try {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use Ahc\Jwt\JWT;
|
||||
use Appwrite\Auth\Auth;
|
||||
use Appwrite\Auth\Authentication;
|
||||
use Appwrite\Event\Build;
|
||||
use Appwrite\Event\Delete;
|
||||
use Appwrite\Event\Event;
|
||||
|
@ -1532,7 +1533,8 @@ Http::post('/v1/functions/:functionId/executions')
|
|||
->inject('queueForFunctions')
|
||||
->inject('geodb')
|
||||
->inject('authorization')
|
||||
->action(function (string $functionId, string $body, bool $async, string $path, string $method, array $headers, Response $response, Document $project, Database $dbForProject, Document $user, Event $queueForEvents, Usage $queueForUsage, string $mode, Func $queueForFunctions, Reader $geodb, Authorization $authorization) {
|
||||
->inject('authentication')
|
||||
->action(function (string $functionId, string $body, bool $async, string $path, string $method, array $headers, Response $response, Document $project, Database $dbForProject, Document $user, Event $queueForEvents, Usage $queueForUsage, string $mode, Func $queueForFunctions, Reader $geodb, Authorization $authorization, Authentication $authentication) {
|
||||
|
||||
$function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId));
|
||||
|
||||
|
@ -1583,7 +1585,7 @@ Http::post('/v1/functions/:functionId/executions')
|
|||
|
||||
foreach ($sessions as $session) {
|
||||
/** @var Utopia\Database\Document $session */
|
||||
if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too
|
||||
if ($session->getAttribute('secret') == Auth::hash($authentication->getSecret())) { // If current session delete the cookies too
|
||||
$current = $session;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ require_once __DIR__ . '/../vendor/autoload.php';
|
|||
use Ahc\Jwt\JWT;
|
||||
use Ahc\Jwt\JWTException;
|
||||
use Appwrite\Auth\Auth;
|
||||
use Appwrite\Auth\Authentication;
|
||||
use Appwrite\Event\Audit;
|
||||
use Appwrite\Event\Build;
|
||||
use Appwrite\Event\Certificate;
|
||||
|
@ -423,8 +424,9 @@ $getProjectDB = new Dependency();
|
|||
$dbForProject = new Dependency();
|
||||
$dbForConsole = new Dependency();
|
||||
$queueForUsage = new Dependency();
|
||||
$authorization = new Dependency();
|
||||
$queueForMails = new Dependency();
|
||||
$authorization = new Dependency();
|
||||
$authentication = new Dependency();
|
||||
$queueForBuilds = new Dependency();
|
||||
$deviceForLocal = new Dependency();
|
||||
$deviceForFiles = new Dependency();
|
||||
|
@ -470,7 +472,8 @@ $user
|
|||
->inject('dbForProject')
|
||||
->inject('dbForConsole')
|
||||
->inject('authorization')
|
||||
->setCallback(function (string $mode, Document $project, Document $console, Request $request, Response $response, Database $dbForProject, Database $dbForConsole, Authorization $authorization) {
|
||||
->inject('authentication')
|
||||
->setCallback(function (string $mode, Document $project, Document $console, Request $request, Response $response, Database $dbForProject, Database $dbForConsole, Authorization $authorization, Authentication $authentication) {
|
||||
$authorization->setDefaultStatus(true);
|
||||
|
||||
Auth::setCookieName('a_session_' . $project->getId());
|
||||
|
@ -509,26 +512,26 @@ $user
|
|||
$session = Auth::decodeSession(((isset($fallback[Auth::$cookieName])) ? $fallback[Auth::$cookieName] : ''));
|
||||
}
|
||||
|
||||
Auth::$unique = $session['id'] ?? '';
|
||||
Auth::$secret = $session['secret'] ?? '';
|
||||
$authentication->setUnique($session['id'] ?? '');
|
||||
$authentication->setSecret($session['secret'] ?? '');
|
||||
|
||||
if (APP_MODE_ADMIN !== $mode) {
|
||||
if ($project->isEmpty()) {
|
||||
$user = new Document([]);
|
||||
} else {
|
||||
if ($project->getId() === 'console') {
|
||||
$user = $dbForConsole->getDocument('users', Auth::$unique);
|
||||
$user = $dbForConsole->getDocument('users', $authentication->getUnique());
|
||||
} else {
|
||||
$user = $dbForProject->getDocument('users', Auth::$unique);
|
||||
$user = $dbForProject->getDocument('users', $authentication->getUnique());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$user = $dbForConsole->getDocument('users', Auth::$unique);
|
||||
$user = $dbForConsole->getDocument('users', $authentication->getUnique());
|
||||
}
|
||||
|
||||
if (
|
||||
$user->isEmpty() // Check a document has been found in the DB
|
||||
|| !Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret)
|
||||
|| !Auth::sessionVerify($user->getAttribute('sessions', []), $authentication->getSecret())
|
||||
) { // Validate user has valid login token
|
||||
$user = new Document([]);
|
||||
}
|
||||
|
@ -577,14 +580,16 @@ $session
|
|||
->setName('session')
|
||||
->inject('user')
|
||||
->inject('project')
|
||||
->setCallback(function (Document $user, Document $project) {
|
||||
->inject('authorization')
|
||||
->inject('authentication')
|
||||
->setCallback(function (Document $user, Document $project, Authorization $authorization, Authentication $authentication) {
|
||||
if ($user->isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sessions = $user->getAttribute('sessions', []);
|
||||
$authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG;
|
||||
$sessionId = Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret, $authDuration);
|
||||
$sessionId = Auth::sessionVerify($user->getAttribute('sessions'), $authentication->getSecret(), $authDuration);
|
||||
|
||||
if (!$sessionId) {
|
||||
return;
|
||||
|
@ -784,6 +789,12 @@ $authorization
|
|||
return new Authorization();
|
||||
});
|
||||
|
||||
$authentication
|
||||
->setName('authentication')
|
||||
->setCallback(function (): Authentication {
|
||||
return new Authentication();
|
||||
});
|
||||
|
||||
$registry
|
||||
->setName('registry')
|
||||
->setCallback(function () use (&$global): Registry {
|
||||
|
@ -1259,9 +1270,10 @@ $container->set($localeCodes);
|
|||
$container->set($dbForProject);
|
||||
$container->set($dbForConsole);
|
||||
$container->set($getProjectDB);
|
||||
$container->set($authorization);
|
||||
$container->set($queueForUsage);
|
||||
$container->set($queueForMails);
|
||||
$container->set($authorization);
|
||||
$container->set($authentication);
|
||||
$container->set($schemaVariable);
|
||||
$container->set($queueForBuilds);
|
||||
$container->set($queueForEvents);
|
||||
|
|
|
@ -483,6 +483,7 @@ $server->onMessage(function (int $connection, string $message) use ($server, $co
|
|||
$projectId = $realtime->connections[$connection]['projectId'];
|
||||
$database = $container->get('dbForConsole');
|
||||
$authorization = $container->get('authorization');
|
||||
$authentication = $container->get('authentication');
|
||||
|
||||
if ($projectId !== 'console') {
|
||||
|
||||
|
@ -525,14 +526,15 @@ $server->onMessage(function (int $connection, string $message) use ($server, $co
|
|||
}
|
||||
|
||||
$session = Auth::decodeSession($message['data']['session']);
|
||||
Auth::$unique = $session['id'] ?? '';
|
||||
Auth::$secret = $session['secret'] ?? '';
|
||||
|
||||
$user = $database->getDocument('users', Auth::$unique);
|
||||
$authentication->setUnique($session['id'] ?? '');
|
||||
$authentication->setSecret($session['secret'] ?? '');
|
||||
|
||||
$user = $database->getDocument('users', $authorization->getUnique());
|
||||
|
||||
if (
|
||||
empty($user->getId()) // Check a document has been found in the DB
|
||||
|| !Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret) // Validate user has valid login token
|
||||
|| !Auth::sessionVerify($user->getAttribute('sessions', []), $authentication->getSecret()) // Validate user has valid login token
|
||||
) {
|
||||
// cookie not valid
|
||||
throw new Exception(Exception::REALTIME_MESSAGE_FORMAT_INVALID, 'Session is not valid.');
|
||||
|
|
|
@ -96,20 +96,6 @@ class Auth
|
|||
*/
|
||||
public static $cookieName = 'a_session';
|
||||
|
||||
/**
|
||||
* User Unique ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $unique = '';
|
||||
|
||||
/**
|
||||
* User Secret Key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $secret = '';
|
||||
|
||||
/**
|
||||
* Set Cookie Name.
|
||||
*
|
||||
|
|
41
src/Appwrite/Auth/Authentication.php
Normal file
41
src/Appwrite/Auth/Authentication.php
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Auth;
|
||||
|
||||
class Authentication
|
||||
{
|
||||
/**
|
||||
* User Unique ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $unique = '';
|
||||
|
||||
/**
|
||||
* User Secret Key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $secret = '';
|
||||
|
||||
public function getUnique(): string
|
||||
{
|
||||
return $this->unique;
|
||||
}
|
||||
|
||||
public function setUnique(string $unique): void
|
||||
{
|
||||
$this->unique = $unique;
|
||||
}
|
||||
|
||||
public function getSecret(): string
|
||||
{
|
||||
return $this->secret;
|
||||
}
|
||||
|
||||
public function setSecret(string $secret): void
|
||||
{
|
||||
$this->secret = $secret;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue