%PDF- %PDF-
| Direktori : /www/varak.net/nextcloud.varak.net/apps_old/apps/passwords/lib/Helper/Token/ |
| Current File : /www/varak.net/nextcloud.varak.net/apps_old/apps/passwords/lib/Helper/Token/ApiTokenHelper.php |
<?php
/*
* @copyright 2024 Passwords App
*
* @author Marius David Wieschollek
* @license AGPL-3.0
*
* This file is part of the Passwords App
* created by Marius David Wieschollek.
*/
namespace OCA\Passwords\Helper\Token;
use Exception;
use OCP\Authentication\Token\IProvider;
use OCP\Authentication\Token\IToken;
use OCA\Passwords\Services\ConfigurationService;
use OCA\Passwords\Services\EnvironmentService;
use OCA\Passwords\Services\LoggingService;
use OCA\Passwords\Services\SessionService;
use OCP\IL10N;
use OCP\IRequest;
use OCP\Security\ISecureRandom;
use Throwable;
/**
* Class ApiTokenHelper
*
* @package OCA\Passwords\Helper\Token
*/
class ApiTokenHelper {
const WEBUI_TOKEN = 'webui/token';
const WEBUI_TOKEN_ID = 'webui/token/id';
/**
* @var null|string
*/
protected ?string $userId;
/**
* ApiTokenHelper constructor.
*
* @param IRequest $request
* @param IL10N $localisation
* @param ISecureRandom $random
* @param LoggingService $logger
* @param SessionService $session
* @param IProvider $tokenProvider
* @param ConfigurationService $config
* @param EnvironmentService $environment
*/
public function __construct(
protected IRequest $request,
protected IL10N $localisation,
protected ISecureRandom $random,
protected LoggingService $logger,
protected SessionService $session,
protected IProvider $tokenProvider,
protected ConfigurationService $config,
protected EnvironmentService $environment
) {
$this->userId = $environment->getUserId();
}
/**
* @return array
*/
public function getWebUiToken(): array {
try {
$token = $this->loadWebUiToken();
if($token !== false) return $token;
return $this->createWebUiToken();
} catch(Throwable $e) {
$this->logger->logException($e);
return ['', ''];
}
}
/**
* @param string $name
* @param bool $permanent
*
* @return array
* @throws Exception
*/
public function createToken(string $name, bool $permanent = false): array {
$userLogin = $this->environment->getUserLogin();
$token = $this->generateRandomDeviceToken();
$password = $this->getUserPassword();
$type = $permanent ? IToken::PERMANENT_TOKEN:IToken::TEMPORARY_TOKEN;
$deviceToken = $this->tokenProvider->generateToken($token, $this->userId, $userLogin, $password, $name, $type);
$deviceToken->setScope(['filesystem' => $this->mustHaveFileSystemPermission()]);
$this->tokenProvider->updateToken($deviceToken);
return [$token, $deviceToken];
}
/**
* @param string $tokenId
*/
public function destroyToken(string $tokenId): void {
$this->tokenProvider->invalidateTokenById(
$this->userId,
$tokenId
);
}
/**
*
*/
public function destroyWebUiToken(): void {
$tokenId = $this->session->get(self::WEBUI_TOKEN_ID);
if(!empty($tokenId)) {
$this->destroyToken($tokenId);
$this->session->delete();
}
}
/**
* @return bool|array
* @throws Exception
*/
protected function loadWebUiToken() {
if($this->environment->isImpersonating()) return false;
$token = $this->session->get(self::WEBUI_TOKEN);
$tokenId = $this->session->get(self::WEBUI_TOKEN_ID);
if($token !== null && $tokenId !== null) {
try {
$webToken = $this->tokenProvider->getTokenById($tokenId);
if($webToken->getId() === $tokenId && $webToken->getUID() === $this->userId) {
return [$token, $webToken->getLoginName()];
} else {
$this->destroyToken($tokenId);
}
} catch(Throwable $e) {
$this->logger
->logException($e)
->error('Failed to load api token for '.$this->userId);
}
}
return false;
}
/**
* @return array
* @throws Exception
*/
protected function createWebUiToken(): array {
$name = $this->getTokenName();
[$token, $deviceToken] = $this->createToken($name);
$this->session->set(self::WEBUI_TOKEN, $token);
$this->session->set(self::WEBUI_TOKEN_ID, $deviceToken->getId());
$this->session->save();
return [$token, $deviceToken->getLoginName()];
}
/**
* @return null|string
*/
protected function getUserPassword(): ?string {
try {
$password = $this->environment->getUserPassword();
return empty($password) ? null:$password;
} catch(Throwable $e) {
$this->logger->logException($e);
}
return null;
}
/**
* @return string
* @throws Exception
*/
protected function generateRandomDeviceToken(): string {
$groups = [];
for($i = 0; $i < 5; $i++) {
$groups[] = $this->random->generate(5, ISecureRandom::CHAR_HUMAN_READABLE);
}
$token = implode('-', $groups);
if(strlen($token) < 29) {
throw new Exception('Token generation failed. Did not generate enough random numbers');
}
return $token;
}
/**
* @return string
*/
protected function getTokenName(): string {
if($this->environment->isImpersonating()) {
return
$this->localisation->t(
'%2$s via Impersonate %1$s - %3$s@%4$s',
[
date('d.m.y H:i'),
$this->environment->getRealUser()->getDisplayName(),
$this->environment->getRealUser()->getUID(),
$this->request->getRemoteAddress()
]
);
}
return $this->localisation->t(
'Passwords Session %s - %s@%s',
[
date('d.m.y H:i'),
$this->environment->getUserLogin(),
$this->request->getRemoteAddress()
]
);
}
/**
* @return bool
*/
protected function mustHaveFileSystemPermission(): bool {
return $this->config->isAppEnabled('encryption') ||
$this->config->isAppEnabled('groupfolders') ||
$this->config->isAppEnabled('files_external');
}
}