diff --git a/cmd/serve.go b/cmd/serve.go
index df44a203310d8eec099bb8d0bdf79f4524c08d8b..1eb4b57ef18fdc870bd9aa59e63a33c3563022b1 100644
--- a/cmd/serve.go
+++ b/cmd/serve.go
@@ -226,6 +226,9 @@ func init() {
 	flags.String("onlyoffice-url", "", "URL for the OnlyOffice server")
 	checkNoErr(viper.BindPFlag("office.default.onlyoffice_url", flags.Lookup("onlyoffice-url")))
 
+	flags.String("onlyoffice-inbox-secret", "", "Secret used for signing requests to the OnlyOffice server")
+	checkNoErr(viper.BindPFlag("office.default.onlyoffice_inbox_secret", flags.Lookup("onlyoffice-inbox-secret")))
+
 	flags.String("password-reset-interval", "15m", "minimal duration between two password reset")
 	checkNoErr(viper.BindPFlag("password_reset_interval", flags.Lookup("password-reset-interval")))
 
diff --git a/cozy.example.yaml b/cozy.example.yaml
index 252ad7daa3f00d103528ded23f067f66c20f88d3..3ab4cbeeca28ba3637a4af6ba3221c7613410a65 100644
--- a/cozy.example.yaml
+++ b/cozy.example.yaml
@@ -257,6 +257,7 @@ move:
 office:
   default:
     onlyoffice_url: https://documentserver.cozycloud.cc/
+    onlyoffice_inbox_secret: inbox_secret
 
 # [internal usage] Cloudery configuration
 clouderies:
diff --git a/docs/docker.md b/docs/docker.md
index 177a2dcdd8af24394a8ea86c28ebbee5938f10fe..25c04672bf852b2952cc528bdccda4d99b11e64e 100644
--- a/docs/docker.md
+++ b/docs/docker.md
@@ -67,7 +67,7 @@ $ docker run -it --rm --name=oodev --net=host cozy/onlyoffice-dev
 and run the stack with:
 
 ```bash
-$ cozy-stack serve --disable-csp --onlyoffice-url=http://localhost:8000/
+$ cozy-stack serve --disable-csp --onlyoffice-url=http://localhost:8000/ --onlyoffice-inbox-secret=inbox_secret
 ```
 
 If you need to rebuild it, you can do that with:
diff --git a/docs/office.md b/docs/office.md
index 6e1f56b6562f1b828c72d9f8c5e8b6e9c4be6176..1ae664540b1132d9bae84391f414170095cc9ce1 100644
--- a/docs/office.md
+++ b/docs/office.md
@@ -88,6 +88,7 @@ Content-Type: application/vnd.api+json
       "public_name": "Bob",
       "onlyoffice": {
         "url": "https://documentserver/",
+        "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.t-IDcSemACt8x4iTMCda8Yhe3iZaWbvV5XKSTbuAn0M",
         "documentType": "word",
         "document": {
           "filetype": "docx",
diff --git a/model/office/open.go b/model/office/open.go
index 070ecb68fbc9dd02bb8916708022d37248a5a220..b7f70480b8525e5a75d539915654ff13a93cbdf5 100644
--- a/model/office/open.go
+++ b/model/office/open.go
@@ -9,6 +9,7 @@ import (
 	"github.com/cozy/cozy-stack/pkg/consts"
 	"github.com/cozy/cozy-stack/pkg/couchdb"
 	"github.com/cozy/cozy-stack/pkg/jsonapi"
+	jwt "gopkg.in/dgrijalva/jwt-go.v3"
 )
 
 type apiOfficeURL struct {
@@ -23,21 +24,22 @@ type apiOfficeURL struct {
 }
 
 type onlyOffice struct {
-	URL  string `json:"url"`
-	Type string `json:"documentType"`
-	Doc  struct {
-		Filetype string `json:"filetype"`
+	URL   string `json:"url,omitempty"`
+	Token string `json:"token,omitempty"`
+	Type  string `json:"documentType"`
+	Doc   struct {
+		Filetype string `json:"filetype,omitempty"`
 		Key      string `json:"key"`
-		Title    string `json:"title"`
+		Title    string `json:"title,omitempty"`
 		URL      string `json:"url"`
 		Info     struct {
 			Owner    string `json:"owner,omitempty"`
-			Uploaded string `json:"uploaded"`
+			Uploaded string `json:"uploaded,omitempty"`
 		} `json:"info"`
 	} `json:"document"`
 	Editor struct {
 		Callback string `json:"callbackUrl"`
-		Lang     string `json:"lang"`
+		Lang     string `json:"lang,omitempty"`
 		Mode     string `json:"mode"`
 	} `json:"editor"`
 }
@@ -53,6 +55,25 @@ func (o *apiOfficeURL) Included() []jsonapi.Object             { return nil }
 func (o *apiOfficeURL) Links() *jsonapi.LinksList              { return nil }
 func (o *apiOfficeURL) Fetch(field string) []string            { return nil }
 
+func (o *apiOfficeURL) sign(cfg *config.Office) (string, error) {
+	if cfg == nil || cfg.InboxSecret == "" {
+		return "", nil
+	}
+
+	claims := *o.OO
+	claims.URL = ""
+	claims.Doc.Filetype = ""
+	claims.Doc.Title = ""
+	claims.Doc.Info.Owner = ""
+	claims.Doc.Info.Uploaded = ""
+	claims.Editor.Lang = ""
+	token := jwt.NewWithClaims(jwt.SigningMethodHS256, &claims)
+	return token.SignedString([]byte(cfg.InboxSecret))
+}
+
+// Valid is a method of the jwt.Claims interface
+func (o *onlyOffice) Valid() error { return nil }
+
 // Opener can be used to find the parameters for opening an office document.
 type Opener struct {
 	*sharing.FileOpener
@@ -154,6 +175,11 @@ func (o *Opener) openLocalDocument(memberIndex int, readOnly bool) (*apiOfficeUR
 	doc.OO.Editor.Lang = o.Inst.Locale
 	doc.OO.Editor.Mode = mode
 
+	token, err := doc.sign(cfg)
+	if err != nil {
+		return nil, err
+	}
+	doc.OO.Token = token
 	return &doc, nil
 }
 
diff --git a/pkg/config/config/config.go b/pkg/config/config/config.go
index 16e7a6311fd78e6bfe89e51054855ee7cb78d3f8..1bbcb31f8641774166b0121dfc54093504292e0d 100644
--- a/pkg/config/config/config.go
+++ b/pkg/config/config/config.go
@@ -221,6 +221,7 @@ type Move struct {
 // documents
 type Office struct {
 	OnlyOfficeURL string
+	InboxSecret   string
 }
 
 // Notifications contains the configuration for the mobile push-notification
@@ -947,14 +948,17 @@ func makeOffice(v *viper.Viper) (map[string]Office, error) {
 		if !ok {
 			return nil, errors.New("Bad format in the office section of the configuration file")
 		}
+		inbox, _ := ctx["onlyoffice_inbox_secret"].(string)
 		office[k] = Office{
 			OnlyOfficeURL: url,
+			InboxSecret:   inbox,
 		}
 	}
 
 	if url := v.GetString("office.default.onlyoffice_url"); url != "" {
 		office[DefaultInstanceContext] = Office{
 			OnlyOfficeURL: url,
+			InboxSecret:   v.GetString("office.default.onlyoffice_inbox_secret"),
 		}
 	}
 
diff --git a/scripts/onlyoffice-dev/Dockerfile b/scripts/onlyoffice-dev/Dockerfile
index b6ba452819ce790fc7c8d4d76c00e3afed97ee41..eef64e0f7d3809a3141355da640a86a008bea0ad 100644
--- a/scripts/onlyoffice-dev/Dockerfile
+++ b/scripts/onlyoffice-dev/Dockerfile
@@ -57,6 +57,7 @@ RUN echo "#!/bin/sh\nexit 0" > /usr/sbin/policy-rc.d && \
     apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 0x8320ca65cb2de8e5 && \
     apt-get -y update && \
     apt-get -yq install onlyoffice-documentserver && \
+	cp /usr/bin/local.json /etc/onlyoffice/documentserver/local.json && \
 	service postgresql stop && \
 	service rabbitmq-server stop && \
 	apt-get clean && \
diff --git a/scripts/onlyoffice-dev/local.json b/scripts/onlyoffice-dev/local.json
new file mode 100644
index 0000000000000000000000000000000000000000..b40e87b188fa393cc8e7382a975a3ee880b45c6a
--- /dev/null
+++ b/scripts/onlyoffice-dev/local.json
@@ -0,0 +1,43 @@
+{
+  "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": "Authorization"
+        },
+        "outbox": {
+          "header": "Authorization"
+        }
+      },
+      "secret": {
+        "inbox": {
+          "string": "inbox_secret"
+        },
+        "outbox": {
+          "string": "outbox_secret"
+        },
+        "session": {
+          "string": "session_secret"
+        }
+      }
+    }
+  },
+  "rabbitmq": {
+    "url": "amqp://guest:guest@localhost"
+  }
+}