use a private/public key logic to generate login tokens for the AIO ui #7686

This commit is contained in:
Zoey
2026-03-05 21:37:03 +01:00
parent 7224f659b3
commit 15721c6d3a
4 changed files with 44 additions and 5 deletions

View File

@@ -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,
];

View File

@@ -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 {

View File

@@ -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();

View File

@@ -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,