- Home
- Docs
- Installation and configuration
- Enterprise
- Docker version
- Validating MD5 signatures for ONLYOFFICE Docs secure links
Validating MD5 signatures for ONLYOFFICE Docs secure links
Overview
ONLYOFFICE Docs uses secure links with MD5 signatures to protect access to cached files.
These links contain the md5 and expires parameters and are generated internally by the CoAuthoring service and validated via NGINX.
To validate or reproduce these MD5 hashes (e.g., for implementing your own proxy or security layer), follow the instructions below.
Generating MD5 signature
The MD5 signature is calculated using the following formula:
md5 = BASE64URL(MD5(<expires><uri><secret>))
Where:
<expires>is the numeric value from theexpiresquery parameter in the URL;<uri>is the full request path (without domain or query string), starting from/cache/files/...;<secret>is the shared secret used by ONLYOFFICE Docs, typically set via theSECURE_LINK_SECRETenvironment variable or in the configuration files.
To generate the hash, follow these steps:
- Concatenate
<expires>,<uri>, and<secret>into a single string. - Compute the binary MD5 (e.g.,
md5($string, true)in PHP). - Encode it using Base64.
-
Convert the Base64 string to a URL-safe format by:
- replacing
+with-; - replacing
/with_; - removing trailing
=.
- replacing
Configuring the secure link secret
The secret used to generate the secure link signature can be set in three ways:
local.json differs from the one in ds.conf, link validation will fail. This is a common issue after updates — make sure the values are in sync.
-
Environment variable (Docker only)
Set an environment variable when running the container:
SECURE_LINK_SECRET=your_secret_here -
local.json configuration file
Set the storage.fs.secretString parameter in the
local.jsonfile, which can be found at the following path:- For Windows -
%ProgramFiles%\ONLYOFFICE\DocumentServer\config\local.json - For Linux -
/etc/onlyoffice/documentserver/local.json - For Docker -
/etc/onlyoffice/documentserver/local.json(within the Docker container)
{ "storage": { "fs": { "secretString": "your_secret_here" } } } - For Windows -
-
NGINX configuration file
Set the
$secure_link_secretparameter in theds.conffile, which can be found at the following path:- For Windows -
%ProgramFiles%\ONLYOFFICE\DocumentServer\nginx\conf\ds.conf - For Linux -
/etc/onlyoffice/documentserver/nginx/ds.conf - For Docker -
/etc/onlyoffice/documentserver/nginx/ds.conf(within the Docker container)
secure_link_md5 "$secure_link_expires$uri$secure_link_secret"; secure_link $arg_md5,$arg_expires; - For Windows -
Example
Let's consider the following example:
https://example.com/cache/files/data/31.172.71.235__172.18.0.2new.docx1749812378403_5169/output.docx/output.docx?md5=NS2_divLHhVBHdvvU9vbwA&expires=1749813362
Step 1. Extract the parameters
Extract the following parameters from the URL:
expires: "1749813362";uri: "/cache/files/data/31.172.71.235__172.18.0.2new.docx1749812378403_5169/output.docx/output.docx";secret: "eNk2pNcaoWYTkpR7YWxe".
Step 2. Validate MD5 using PHP
The following PHP example demonstrates how to generate and validate the MD5 signature:
<?php
$expires = "1749813362";
$uri = "/cache/files/data/31.172.71.235__172.18.0.2new.docx1749812378403_5169/output.docx/output.docx";
$secure_link_secret = "eNk2pNcaoWYTkpR7YWxe";
// Form the string:<expires><uri><secure_link_secret>
$string_to_hash = $expires . $uri . $secure_link_secret;
// Calculate MD5 hash
$md5_hash = md5($string_to_hash, true);
// Encode to Base64 (URL-safe)
$base64_hash = str_replace(
['+', '/', '='],
['-', '_', ''],
base64_encode($md5_hash)
);
// Output the result
echo "String to hash: " . $string_to_hash . "\n";
echo "Generated MD5 hash: " . $base64_hash . "\n";
echo "Expected MD5 hash: NS2_divLHhVBHdvvU9vbwA\n";
?>
Step 3. Compare the signatures
The function calculates the following MD5 signature:
NS2_divLHhVBHdvvU9vbwA
This matches the md5 parameter in the URL. Therefore, the request is valid and can be confirmed.
Known issues
- Always use the URI, not the full URL.
- Make sure your secret matches the configuration.
- Do not use the
urlExpiresparameter for hashing. This parameter is defined indefault.json(not inlocal.json) and controls link lifetime configuration, not the value used in the MD5 formula. Always use the actualexpiresvalue from the URL query string. - Ensure Base64 encoding is URL-safe.