181 lines
4.4 KiB
Markdown
181 lines
4.4 KiB
Markdown
# JWT Authentication Fix for OnlyOffice Docs 7.1+
|
|
|
|
## Problem
|
|
|
|
The error you encountered:
|
|
|
|
```
|
|
[ERROR] nodeJS - auth missing required parameter document.key (since 7.1 version)
|
|
```
|
|
|
|
And the Chinese error dialog: "错误 - 文档安全令牌的格式不正确" (Document security token format is incorrect)
|
|
|
|
## Root Cause
|
|
|
|
Starting with OnlyOffice Docs version 7.1, when JWT authentication is enabled on the server, the entire configuration object must be signed with a JWT token. Simply passing a pre-generated JWT token as a separate field is not sufficient.
|
|
|
|
According to the [ONLYOFFICE signature documentation](https://api.onlyoffice.com/docs/docs-api/additional-api/signature/), the token must:
|
|
|
|
1. Be generated using the JWT secret key configured on the server
|
|
2. Include the entire configuration object (including `document.key` and all other parameters)
|
|
3. Use the HS256 algorithm
|
|
|
|
## Changes Made
|
|
|
|
### 1. Added JWT Package
|
|
|
|
**File: `pubspec.yaml`**
|
|
|
|
Added `dart_jsonwebtoken: ^2.14.1` to properly sign JWT tokens.
|
|
|
|
```yaml
|
|
dependencies:
|
|
flutter:
|
|
sdk: flutter
|
|
crypto: ^3.0.7
|
|
webview_flutter: ^4.13.0
|
|
webview_flutter_android: ^4.10.10
|
|
webview_flutter_wkwebview: ^3.0.0
|
|
dart_jsonwebtoken: ^2.14.1 # NEW
|
|
```
|
|
|
|
### 2. Updated OnlyOfficeViewer Widget
|
|
|
|
**File: `lib/onlyoffice_viewer.dart`**
|
|
|
|
**Changed parameter name:**
|
|
- ❌ Old: `final String? token;`
|
|
- ✅ New: `final String? jwtSecret;`
|
|
|
|
**Updated JWT signing logic:**
|
|
|
|
```dart
|
|
// Sign the entire config with JWT if secret is provided
|
|
if (widget.jwtSecret != null && widget.jwtSecret!.isNotEmpty) {
|
|
final jwt = JWT(config);
|
|
final token = jwt.sign(SecretKey(widget.jwtSecret!), algorithm: JWTAlgorithm.HS256);
|
|
config['token'] = token;
|
|
}
|
|
```
|
|
|
|
The key difference: Instead of just adding a pre-made token to the config, we now:
|
|
1. Create a JWT from the **entire config object**
|
|
2. Sign it with the **secret key** using HS256 algorithm
|
|
3. Add the resulting signed token to the config
|
|
|
|
### 3. Updated Example App
|
|
|
|
**File: `example/lib/main.dart`**
|
|
|
|
```dart
|
|
// Old:
|
|
static const String jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...';
|
|
|
|
// New:
|
|
static const String jwtSecret = '6Yr6DGoVV3ACS6GtVgdH453mXxLftd6Q';
|
|
|
|
// Usage:
|
|
OnlyOfficeViewer(
|
|
onlyOfficeServerUrl: onlyOfficeServerUrl,
|
|
fileUrl: currentDoc.url,
|
|
jwtSecret: jwtSecret, // Pass the secret, not a pre-made token
|
|
)
|
|
```
|
|
|
|
### 4. Updated Tests
|
|
|
|
**File: `test/onlyoffice_viewer_unit_test.dart`**
|
|
|
|
- Updated all test cases to use `jwtSecret` instead of `token`
|
|
- Added new test to verify JWT token generation and validation
|
|
- Updated TestHelper to match the real implementation
|
|
|
|
## How to Use
|
|
|
|
### For Your Server Configuration
|
|
|
|
You need to provide the **JWT secret** that matches your OnlyOffice server configuration. This secret is configured in your OnlyOffice server's `local.json`:
|
|
|
|
```json
|
|
{
|
|
"services": {
|
|
"CoAuthoring": {
|
|
"secret": {
|
|
"inbox": {
|
|
"string": "YOUR_SECRET_HERE"
|
|
},
|
|
"outbox": {
|
|
"string": "YOUR_SECRET_HERE"
|
|
}
|
|
},
|
|
"token": {
|
|
"enable": {
|
|
"browser": true,
|
|
"request": {
|
|
"inbox": true,
|
|
"outbox": true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Example Usage
|
|
|
|
```dart
|
|
OnlyOfficeViewer(
|
|
onlyOfficeServerUrl: 'https://document.23544.com/',
|
|
fileUrl: 'https://example.com/document.pptx',
|
|
jwtSecret: '6Yr6DGoVV3ACS6GtVgdH453mXxLftd6Q', // Your server's JWT secret
|
|
)
|
|
```
|
|
|
|
## What Gets Signed
|
|
|
|
The JWT token now contains the entire configuration object:
|
|
|
|
```dart
|
|
{
|
|
'document': {
|
|
'fileType': 'pptx',
|
|
'key': 'sha256_hash_of_url',
|
|
'title': 'document.pptx',
|
|
'url': 'https://example.com/document.pptx',
|
|
},
|
|
'documentType': 'slide',
|
|
'editorConfig': {
|
|
'mode': 'view',
|
|
'lang': 'zh-CN'
|
|
},
|
|
'type': 'mobile',
|
|
}
|
|
```
|
|
|
|
This entire object is signed with HS256 algorithm using your secret, and the resulting JWT is added as the `token` field.
|
|
|
|
## Security Note
|
|
|
|
⚠️ **Never commit your JWT secret to version control!**
|
|
|
|
Store it securely:
|
|
- Use environment variables
|
|
- Use secure configuration management
|
|
- Use encrypted secret storage
|
|
|
|
## References
|
|
|
|
- [ONLYOFFICE Signature Documentation](https://api.onlyoffice.com/docs/docs-api/additional-api/signature/)
|
|
- [JWT.io - Introduction to JSON Web Tokens](https://jwt.io/introduction)
|
|
|
|
## Testing
|
|
|
|
All tests pass successfully:
|
|
|
|
```bash
|
|
flutter test test/onlyoffice_viewer_unit_test.dart
|
|
# ✅ All 20 tests passed!
|
|
```
|
|
|