diff --git a/app/lib/Settings/Admin.php b/app/lib/Settings/Admin.php index 36fbd01b..2abc99fd 100644 --- a/app/lib/Settings/Admin.php +++ b/app/lib/Settings/Admin.php @@ -55,7 +55,12 @@ class Admin implements ISettings { $lastUpdateCheckTimestamp = $this->config->getAppValue('core', 'lastupdatedat'); $lastUpdateCheck = $this->dateTimeFormatter->formatDateTime($lastUpdateCheckTimestamp); - $token = urlencode(getenv('AIO_TOKEN')); + $privateKeyBase64 = getenv('AIO_TOKEN'); + $privateKeyBin = sodium_base642bin($privateKeyBase64, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING); + $timestamp = (string) time(); + $tokenBin = sodium_crypto_sign($timestamp, $privateKeyBin); + $token = sodium_bin2base64($tokenBin, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING); + $params = [ 'AIOLoginUrl' => 'https://' . getenv('AIO_URL') . '/api/auth/getlogin' . '?token=' . $token, ]; diff --git a/php/src/Auth/AuthManager.php b/php/src/Auth/AuthManager.php index c2c0c7ac..9a6bab67 100644 --- a/php/src/Auth/AuthManager.php +++ b/php/src/Auth/AuthManager.php @@ -20,7 +20,30 @@ readonly class AuthManager { } public function CheckToken(string $token) : bool { - return hash_equals($this->configurationManager->aioToken, $token); + $publicKeyBase64 = $this->configurationManager->aioPublicKey; + if ($publicKeyBase64 === '' || $token === '') { + return false; + } + + try { + $publicKeyBin = sodium_base642bin($publicKeyBase64, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING); + $tokenBin = sodium_base642bin($token, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING); + } catch (\SodiumException) { + return false; + } + + $timestamp = sodium_crypto_sign_open($tokenBin, $publicKeyBin); + + if ($timestamp === false) { + return false; + } + + $timeElapsed = time() - (int) $timestamp; + if ($timeElapsed > 60) { + return false; + } + + return true; } public function SetAuthState(bool $isLoggedIn) : void { diff --git a/php/src/Controller/DockerController.php b/php/src/Controller/DockerController.php index dc3a292e..36c72ad9 100644 --- a/php/src/Controller/DockerController.php +++ b/php/src/Controller/DockerController.php @@ -232,7 +232,16 @@ readonly class DockerController { } public function startTopContainer(bool $pullImage, ?\Closure $addToStreamingResponseBody = null) : void { - $this->configurationManager->aioToken = bin2hex(random_bytes(24)); + $keypair = sodium_crypto_sign_keypair(); + + $privateKeyBin = sodium_crypto_sign_secretkey($keypair); + $publicKeyBin = sodium_crypto_sign_publickey($keypair); + + $privateKeyBase64 = sodium_bin2base64($privateKeyBin, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING); + $publicKeyBase64 = sodium_bin2base64($publicKeyBin, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING); + + $this->configurationManager->aioPublicKey = $publicKeyBase64; + $this->configurationManager->aioPrivateKey = $privateKeyBase64; // Stop domaincheck since apache would not be able to start otherwise $this->StopDomaincheckContainer(); diff --git a/php/src/Data/ConfigurationManager.php b/php/src/Data/ConfigurationManager.php index 4b23f746..93afb5d8 100644 --- a/php/src/Data/ConfigurationManager.php +++ b/php/src/Data/ConfigurationManager.php @@ -12,9 +12,11 @@ class ConfigurationManager private array $config = []; + public string $aioPrivateKey = ''; + private bool $noWrite = false; - public string $aioToken { + public string $aioPublicKey { get => $this->get('AIO_TOKEN', ''); set { $this->set('AIO_TOKEN', $value); } } @@ -1017,7 +1019,7 @@ class ConfigurationManager return match ($placeholder) { 'NC_DOMAIN' => $this->domain, 'NC_BASE_DN' => $this->getBaseDN(), - 'AIO_TOKEN' => $this->aioToken, + 'AIO_TOKEN' => $this->aioPrivateKey, 'BORGBACKUP_REMOTE_REPO' => $this->borgRemoteRepo, 'BORGBACKUP_MODE' => $this->backupMode, 'AIO_URL' => $this->aioUrl,