Nextcloud+onlyoffice 403 Forbidden nginx

Hi,

First of all, I’m going to admit that i’m not professional server admin, this is more like my hobby and I’m still learning.

So, after recent (about week ago) docker automated update of my docservice container (i’m using watchtower), integration stopped working. Nextcloud connector shows this message:

(Client error: `GET https://xxx.xxxx.xxxx.xx/cache/files/data/conv_check_1441340148_docx/output.docx/check_1441340148.docx?md5=hKZsGY_JOCoTwmL-GckOlA&expires=1664352867&filename=check_1441340148.docx` resulted in a `403 Forbidden` response:

403 Forbidden

403 Forbidden
nginx

When i use DS example, it shows message:

The document security token is not correctly formed. Please contact your Document Server administrator.

My apache2 vhost:

<VirtualHost *:443>
     ServerName xxxxxxx
     DocumentRoot "/srv/www/htdocs/onlyoffice"
     ProxyPass /.well-known/ !
     ProxyPreserveHost On
     ProxyPass "/" "http://localhost:88/"
     ProxyPassReverse "/" "http://localhost:88/"

     RewriteEngine on
# Some rewrite rules in this file were disabled on your HTTPS site,
# because they have the potential to create redirection loops.

#      RewriteCond %{SERVER_NAME} =xxxxx
#      RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

     <IfModule mod_headers.c>
     RewriteEngine On
     SetEnvIf Host "^(.*)$" THE_HOST=$1
     RequestHeader set X-Forwarded-Proto "https"
     ProxyAddHeaders Off

     SetEnvIf Host "^(.*)$" THE_HOST=$1
     RequestHeader setifempty X-Forwarded-Proto https
     RequestHeader setifempty X-Forwarded-Host %{THE_HOST}e

     ProxyPassMatch (.*)(\/websocket)$ "ws://localhost:88/$1$2"
     ProxyPass / "http://localhost:88/"
     ProxyPassReverse / "http://localhost:88/"

     </IfModule>

Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/xxxxl/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/xxxx/privkey.pem
</VirtualHost>
</IfModule>

Nextcloud config.php

 'onlyoffice' =>
  array (
    'verify_peer_off' => true,
    'jwt_secret' => 'secret',
    'jwt_header' => 'AuthorizationJWT'
  ),

Onlyoffice local.json

{
  "services": {
    "CoAuthoring": {
      "sql": {
        "type": "postgres",
        "dbHost": "localhost",
        "dbPort": "5432",
        "dbName": "onlyoffice",
        "dbUser": "onlyoffice",
        "dbPass": "onlyoffice"
      },
      "token": {
        "enable": {
          "request": {
            "inbox": true,
            "outbox": true
          },
          "browser": true
        },
        "inbox": {
          "header": "AuthorizationJWT"
        },
        "outbox": {
          "header": "AuthorizationJWT"
        }
      },
      "secret": {
        "inbox": {
          "string": "secret"
        },
        "outbox": {
          "string": "secret"
        },
        "session": {
          "string": "secret"
        }
      }
    }
  },
  "rabbitmq": {
    "url": "amqp://guest:guest@localhost"
  }
}

With configuration above, everything worked fine until last docker image update. I tried looking for solution in other topics, yet i found none.

Connector: 7.5.4, DS: 7.2

Any idea what should i do?

Hello @Viis
Please double-check your local.json file. In the DSv.7.2 we have implemented random key for JWT. So JWT secret could change.
If config file is OK, please reproduce the issue (go to connector page > click Save button) and provide us with whole Document server logs folder.
One more thing, would you mind checking mutual availability between servers? Go to DS host and run wget https://nextcloud_domain_name. And vice versa, from Nextcloud host run wget https://DS_domain name.

Thanks for response.

  1. HERE is documentserver log folder, pulled directly from container. I’ll send password to open archive in private message.

  2. I have double checked JWT secret with

docker exec e4f7e173b25f /var/www/onlyoffice/documentserver/npm/json -f /etc/onlyoffice/documentserver/local.json 'services.CoAuthoring.secret.session.string'

and it matches with nextcloud config.php and connector password field (though it’s different than what i wrote in first post, because didn’t want to share it publicly).

  1. There is no problem using wget to reach ds ->nextcloud and nextcloud ->ds, both results in saving index.html, if it’s what should’ve happen.

I got the same error with a fresh installation documentserver-ee on ubuntu (no docker).

Found this in local.jason whichwas new since version 7.2.0

“storage”: {
“fs”: {
“secretString”: “SomeString different from other jwt secrets”
}
}

Commenting this out resolved the error notification from onlyoffice nextcloud app.

Maybe stuff member can verify if this should be set to the same secreat as ,inbox", ,outbox" and ,session"

Regards Lukas

I would do the same with my local.json, but i have a script replacing whole content of this file, so it is the same after watchtower updates container as it was before, and since i don’t have anything like this in my local.json, default values stored in default.json should be put to use.

Correct me If i’m wrong, but having it commented out or absent in local.json is basically same thing, right? As commented out → ommited → default values, and same goes for: not present → default values.

Well, i would appreciate onlyoffice 7.2 local.json file anyway, maybe i’ll find something in there that is missing in my current config. Anyone wiling to share? (since i’m retarded and had it autoreplaced by script…)

Hello @lmensinck

This section defines the secret string which is used to sign the URL. We have information about it here: Configuring ONLYOFFICE Docs Developer Edition - ONLYOFFICE
When editing session is over, Document server builds a file and the link to the file in its cache. It uses MD5 hash to secure it.
So this section needs to improve security of your Document server.

@Viis I have sent you a message via PM about your described situation.

I would do the same with my local.json, but i have a script replacing whole content of this file

local.json file generates during the installation. I’ll send you example from my test machine in a few minutes, but I think it’s better just to re-install Document server.

I had a old server so i creat a new server the new server had the same setup as on Ubuntu, Ngix etc i copied the ds.conf from old to new server. i was getting error that nextcloud can not access 403 So what i noticed the old server had set $secure_link_secret verysecretstring; in the ds.conf and the new server had set $secure_link_secret kkjnjkok1kk1k1nkj1; so when i copied the old ds.conf set $secure_link_secret kkjnjkok1kk1k1nkj1; got removed so i had to update the following from set $secure_link_secret verysecretstring; $secure_link_secret kkjnjkok1kk1k1nkj1; and 403 went away . Why is this ? Before the server accepted $secure_link_secret verysecretstring;

The secretstring has been motified for this post server is different just wnated to give an example

{"reqId":"xf8a8MSm0Facw1UitFeI","level":3,"time":"2022-10-11T16:08:06+00:00","remoteAddr":"10.0.10.90","user":"axheli","app":"onlyoffice","method":"PUT","url":"/apps/onlyoffice/ajax/settings/address","message":"Request converted file on check error","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36","version":"25.0.0.15","exception":{"Exception":"GuzzleHttp\\Exception\\ClientException","Message":"Client error: `GET https://onlyoffice.server.com:7342/cache/files/data/conv_check_735773261_docx/output.docx/check_735773261.docx?md5=BYXwW03TcpjdcuGUqf6hfw&expires=1665505387&filename=check_735773261.docx` resulted in a `403 Forbidden` response:\n<html>\r\n<head><title>403 Forbidden</title></head>\r\n<body>\r\n<center><h1>403 Forbidden</h1></center>\r\n<hr><center>nginx</c (truncated...)\n","Code":403,"Trace":[{"file":"/var/www/nextcloud/3rdparty/guzzlehttp/guzzle/src/Middleware.php","line":69,"function":"create","class":"GuzzleHttp\\Exception\\RequestException","type":"::"},{"file":"/var/www/nextcloud/3rdparty/guzzlehttp/promises/src/Promise.php","line":204,"function":"GuzzleHttp\\{closure}","class":"GuzzleHttp\\Middleware","type":"::","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/nextcloud/3rdparty/guzzlehttp/promises/src/Promise.php","line":153,"function":"callHandler","class":"GuzzleHttp\\Promise\\Promise","type":"::"},{"file":"/var/www/nextcloud/3rdparty/guzzlehttp/promises/src/TaskQueue.php","line":48,"function":"GuzzleHttp\\Promise\\{closure}","class":"GuzzleHttp\\Promise\\Promise","type":"::","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/nextcloud/3rdparty/guzzlehttp/promises/src/Promise.php","line":248,"function":"run","class":"GuzzleHttp\\Promise\\TaskQueue","type":"->"},{"file":"/var/www/nextcloud/3rdparty/guzzlehttp/promises/src/Promise.php","line":224,"function":"invokeWaitFn","class":"GuzzleHttp\\Promise\\Promise","type":"->"},{"file":"/var/www/nextcloud/3rdparty/guzzlehttp/promises/src/Promise.php","line":269,"function":"waitIfPending","class":"GuzzleHttp\\Promise\\Promise","type":"->"},{"file":"/var/www/nextcloud/3rdparty/guzzlehttp/promises/src/Promise.php","line":226,"function":"invokeWaitList","class":"GuzzleHttp\\Promise\\Promise","type":"->"},{"file":"/var/www/nextcloud/3rdparty/guzzlehttp/promises/src/Promise.php","line":62,"function":"waitIfPending","class":"GuzzleHttp\\Promise\\Promise","type":"->"},{"file":"/var/www/nextcloud/3rdparty/guzzlehttp/guzzle/src/Client.php","line":187,"function":"wait","class":"GuzzleHttp\\Promise\\Promise","type":"->"},{"file":"/var/www/nextcloud/lib/private/Http/Client/Client.php","line":218,"function":"request","class":"GuzzleHttp\\Client","type":"->"},{"file":"/var/www/nextcloud/apps/onlyoffice/lib/documentservice.php","line":374,"function":"get","class":"OC\\Http\\Client\\Client","type":"->"},{"file":"/var/www/nextcloud/apps/onlyoffice/lib/documentservice.php","line":458,"function":"Request","class":"OCA\\Onlyoffice\\DocumentService","type":"->"},{"file":"/var/www/nextcloud/apps/onlyoffice/controller/settingscontroller.php","line":174,"function":"checkDocServiceUrl","class":"OCA\\Onlyoffice\\DocumentService","type":"->"},{"file":"/var/www/nextcloud/lib/private/AppFramework/Http/Dispatcher.php","line":225,"function":"SaveAddress","class":"OCA\\Onlyoffice\\Controller\\SettingsController","type":"->"},{"file":"/var/www/nextcloud/lib/private/AppFramework/Http/Dispatcher.php","line":133,"function":"executeController","class":"OC\\AppFramework\\Http\\Dispatcher","type":"->"},{"file":"/var/www/nextcloud/lib/private/AppFramework/App.php","line":172,"function":"dispatch","class":"OC\\AppFramework\\Http\\Dispatcher","type":"->"},{"file":"/var/www/nextcloud/lib/private/Route/Router.php","line":298,"function":"main","class":"OC\\AppFramework\\App","type":"::"},{"file":"/var/www/nextcloud/lib/base.php","line":1047,"function":"match","class":"OC\\Route\\Router","type":"->"},{"file":"/var/www/nextcloud/index.php","line":36,"function":"handleRequest","class":"OC","type":"::"}],"File":"/var/www/nextcloud/3rdparty/guzzlehttp/guzzle/src/Exception/RequestException.php","Line":113,"message":"Request converted file on check error","CustomMessage":"Request converted file on check error"},"id":"634599cf2ecfb"}
2 Likes

Changing secure_link_secret to from some random code back to “verysecretstring” worked like a charm. But what should I change and where in nextcloud instance if i want to keep this random code? And what command should i use to retrieve this string from onlyoffice?

PS: Sorry for my late response, i had really busy week.

Hello @axheli
I assume that your servers had different versions of Document server. This way we do not recommend to use old config files. From time to time we change config files during new version release to achieve new features.

@Viis
As far as I see, you had the same issue:

I would do the same with my local.json, but i have a script replacing whole content of this file

You have replaced new data with old one. I believe this is the reason of the issue.

2 Likes

The Nginx 403 Forbidden error occurs when a client attempts to access a section of the webserver without adequate permissions. When Nginx accesses a directory, it attempts to generate an index of its files and present them to the browser or client. However, the default configuration disables directory indexing, leading to the display of the 403 forbidden error instead.

Incorrect Index File

The try_files tries the literal path you specify in relation to the defined root directive and sets the internal file pointer. If you have directory indexing off, and is having this problem, it’s probably because the try_files you are using has a directory option:

location / {
  try_files $uri $uri/ /index.html index.php;
}

to

location / {
  try_files $uri /index.html index.php;
}

Incorrectly set permissions

This error can also result from files and directories having incorrectly set permissions. In order to resolve this , change the directories permission to 755 and the file permissions to 644 . Make sure that the user running the Nginx process owns the files. For example, set user to www-data:

sudo chown -R www-data:www-data *

Finally, set the directory and file permissions as:

sudo chmod 755 {dir}
sudo chmod 644 {files}

useful !!! thanks !!! i set DocumentServer\nginx\conf\includes\ds-docservice.conf line 43 verysecretstring to it , and 403 went away ~

useful !!! thanks !!! i set DocumentServer\nginx\conf\includes\ds-docservice.conf line 43 verysecretstring to it , and 403 went away ~

Hello @tcsnzh
We’re glad that you managed the situation. I assume that issue was related to old config file.

Hello @rickberon
Thank you for detailed Nginx guide and description, but I believe that issues described in this thread are related to incorrect config files only. Anyway, we appreciate your share. Please feel free to contact us if you face any issues.

I had this 403 problem when updating from nc 26 to 28 (with an inbetween step at 27)

I found that re-installing was the way to solve it, as I am using a docker-compose setup there were some details that were important, so i’ll share them here:

  1. the old nginx config was the problem in the end, thus i needed to clear my local volume, so that the container would recreate the nginx config (with the secrets all sorted out).

  2. re-installing via the web gui didn’t work (enabling this app makes the server unstable) so i did it via command line:

cd nextcloud/apps
wget https://github.com/ONLYOFFICE/onlyoffice-nextcloud/releases/download/v9.0.0/onlyoffice.tar.gz
tar -xvzf onlyoffice.tar.gz 
rm onlyoffice.tar.gz 
occ app:enable onlyoffice 

then one can go into the gui and click save
and run this to check:
occ onlyoffice:documentserver --check

Hello @gotjoshua
Thank you for your sharing!
I haven’t checked these steps, but it seems that you re-installed the connector app itself. Probably there was an issue on its side after Nextcloud upgrade. However, I hope these actions will help other users in some cases.

indeed i did! It was a bit frustrating to need to use the cli to do so… but it works now, so thats great.

I think it would be great if the team could give the upgrade process a bit more care and attention, but i also understand that there are many integrations and many install methods to track/test…

to need to use the cli to do so

That’s strange, because the connector app should be uninstalled correctly via ‘Apps’ menu on the Nextcloud side. Did you face any issue there when you tried to reinstall the connector app (in web interface)?