From 50f5c20b1d2bacb08100f1cc43bbf2a8ca7ccce6 Mon Sep 17 00:00:00 2001 From: anon8675309 Date: Tue, 25 Oct 2022 03:30:42 -0500 Subject: [PATCH] Exposed leeway setting in the JWT library If the system clock of the document server is even a second slower than the nextcloud server, the JWT token will be rejected as being "not yet valid". This can be seen in the logs (Nextcloud -> Settings -> Administration -> Logging). The error message shown to the user when this happens is more generic: "Error when trying to connect (Error occurred in the document service: Error while downloading the document file to be converted.)" This error message has been reported on the bug tracker several times, but it is not clear when the connection failure was due to imperfectly synchronized clocks and when it was due to network connectivity, DNS issues, the JWT not being sent, the secret being wrong, or some other issue. Here are the tickets that may be fixed by this: https://github.com/ONLYOFFICE/onlyoffice-nextcloud/issues/345 https://github.com/ONLYOFFICE/onlyoffice-nextcloud/issues/548 https://github.com/ONLYOFFICE/onlyoffice-nextcloud/issues/315 https://github.com/ONLYOFFICE/onlyoffice-nextcloud/issues/290 https://github.com/ONLYOFFICE/onlyoffice-nextcloud/issues/127 There's also one on the owncloud fork that may be fixed by this as well: https://github.com/ONLYOFFICE/onlyoffice-owncloud/issues/278 --- appinfo/application.php | 2 ++ controller/settingscontroller.php | 8 ++++++-- js/settings.js | 3 +++ lib/appconfig.php | 28 ++++++++++++++++++++++++++++ templates/settings.php | 3 +++ 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/appinfo/application.php b/appinfo/application.php index bbf013aa..c5386dc3 100644 --- a/appinfo/application.php +++ b/appinfo/application.php @@ -101,6 +101,8 @@ public function register(IRegistrationContext $context): void { if (!class_exists('\\Firebase\\JWT\\JWT')) { require_once __DIR__ . "/../3rdparty/jwt/JWT.php"; } + // Set the leeway for the JWT library in case the system clock is a second off + \Firebase\JWT\JWT::$leeway = $this->appConfig->GetJwtLeeway(); $context->registerService("L10N", function (ContainerInterface $c) { return $c->get("ServerContainer")->getL10N($c->get("AppName")); diff --git a/controller/settingscontroller.php b/controller/settingscontroller.php index 60d4fe0d..7bb8ff3f 100644 --- a/controller/settingscontroller.php +++ b/controller/settingscontroller.php @@ -130,7 +130,8 @@ public function index() { "tagsEnabled" => \OC::$server->getAppManager()->isEnabledForUser("systemtags"), "reviewDisplay" => $this->config->GetCustomizationReviewDisplay(), "theme" => $this->config->GetCustomizationTheme(), - "templates" => $this->GetGlobalTemplates() + "templates" => $this->GetGlobalTemplates(), + "jwtLeeway" => $this->config->GetJwtLeeway() ]; return new TemplateResponse($this->appName, "settings", $data, "blank"); } @@ -152,7 +153,8 @@ public function SaveAddress($documentserver, $storageUrl, $verifyPeerOff, $secret, - $demo + $demo, + $jwtLeeway ) { $error = null; if (!$this->config->SelectDemo($demo === true)) { @@ -163,6 +165,7 @@ public function SaveAddress($documentserver, $this->config->SetVerifyPeerOff($verifyPeerOff); $this->config->SetDocumentServerInternalUrl($documentserverInternal); $this->config->SetDocumentServerSecret($secret); + $this->config->SetJwtLeeway($jwtLeeway); } $this->config->SetStorageUrl($storageUrl); @@ -182,6 +185,7 @@ public function SaveAddress($documentserver, "documentserverInternal" => $this->config->GetDocumentServerInternalUrl(true), "storageUrl" => $this->config->GetStorageUrl(), "secret" => $this->config->GetDocumentServerSecret(true), + "jwtLeeway" => $this->config->GetJwtLeeway(), "error" => $error, "version" => $version, ]; diff --git a/js/settings.js b/js/settings.js index 87adadcb..ae7ead62 100644 --- a/js/settings.js +++ b/js/settings.js @@ -141,6 +141,7 @@ var onlyofficeStorageUrl = ($("#onlyofficeStorageUrl:visible").val() || "").trim(); var onlyofficeVerifyPeerOff = $("#onlyofficeVerifyPeerOff").prop("checked"); var onlyofficeSecret = ($("#onlyofficeSecret:visible").val() || "").trim(); + var onlyofficeJwtLeeway = ($("#onlyofficeJwtLeeway").val() || "0").trim(); var demo = $("#onlyofficeDemo").prop("checked"); $.ajax({ @@ -152,6 +153,7 @@ storageUrl: onlyofficeStorageUrl, verifyPeerOff: onlyofficeVerifyPeerOff, secret: onlyofficeSecret, + jwtLeeway: onlyofficeJwtLeeway, demo: demo }, success: function onSuccess(response) { @@ -161,6 +163,7 @@ $("#onlyofficeInternalUrl").val(response.documentserverInternal); $("#onlyofficeStorageUrl").val(response.storageUrl); $("#onlyofficeSecret").val(response.secret); + $("#onlyofficeJwtLeeway").val(response.jwtLeeway); $(".section-onlyoffice-common, .section-onlyoffice-templates, .section-onlyoffice-watermark").toggleClass("onlyoffice-hide", (!response.documentserver.length && !demo) || !!response.error.length); diff --git a/lib/appconfig.php b/lib/appconfig.php index 47b20b6b..561bfe94 100644 --- a/lib/appconfig.php +++ b/lib/appconfig.php @@ -88,6 +88,13 @@ class AppConfig { */ private $_cryptSecret = "secret"; + /** + * The config key for the allowable leeway in Jwt checks + * + * @var string + */ + private $_jwtLeeway = "JwtLeeway"; + /** * The config key for the default formats * @@ -571,6 +578,27 @@ public function GetDocumentServerSecret($origin = false) { return $secret; } + /** + * Save the Jwt Leeway to the application configuration + * + * @param string $jwtLeeway - number of seconds the docs/nextcloud clock can be off + */ + public function SetJwtLeeway($jwtLeeway) { + $this->logger->debug("Setting JwtLeeway to: " . json_encode($jwtLeeway), ["app" => $this->appName]); + $this->config->setAppValue($this->appName, $this->_jwtLeeway, $jwtLeeway); + } + + /** + * Get the Jwt Leeway + * + * @return string + */ + public function GetJwtLeeway() { + $jwtLeeway = $this->config->getAppValue($this->appName, $this->_jwtLeeway, "0"); + $this->logger->debug("JwtLeeqy: " . json_encode($jwtLeeway), ["app" => $this->appName]); + return $jwtLeeway; + } + /** * Get the secret key from the application configuration * diff --git a/templates/settings.php b/templates/settings.php index fd9d0d88..7140be98 100644 --- a/templates/settings.php +++ b/templates/settings.php @@ -67,6 +67,9 @@

t("Server address for internal requests from ONLYOFFICE Docs")) ?>

" placeholder="" type="text">

+ +

t("Amount of leeway in system clocks between nextcloud and ONLYOFFICE Docs (in seconds)")) ?>

+

" placeholder="0" type="text">