Compare commits

...

5 Commits

Author SHA1 Message Date
35c4dd6a95 Disabled jwt 2017-03-03 17:34:24 +03:00
32aff45d7d Merge pull request #21 from ONLYOFFICE/feature/token
Feature/token
2017-03-03 16:54:38 +03:00
1b73970ebc node: jwt 2017-03-03 16:48:45 +03:00
c014250479 node: moved config in a separate file 2017-03-02 19:38:24 +03:00
b1e216da88 node: upload request without file 2017-03-02 18:52:20 +03:00
6 changed files with 178 additions and 69 deletions

View File

@ -30,6 +30,7 @@ const bodyParser = require("body-parser");
const fileSystem = require("fs");
const formidable = require("formidable");
const syncRequest = require("sync-request");
const jwt = require('jsonwebtoken');
const config = require('config');
const configServer = config.get('server');
const docManager = require("./helpers/docManager");
@ -38,6 +39,10 @@ const fileUtility = require("./helpers/fileUtility");
const siteUrl = configServer.get('siteUrl');
const fileChoiceUrl = configServer.has('fileChoiceUrl') ? configServer.get('fileChoiceUrl') : "";
const plugins = config.get('plugins');
const cfgSignatureEnable = configServer.get('token.enable');
const cfgSignatureUseForRequest = configServer.get('token.useforrequest');
const cfgSignatureSecretExpiresIn = configServer.get('token.expiresIn');
const cfgSignatureSecret = configServer.get('token.secret');
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
@ -135,6 +140,13 @@ app.post("/upload", function (req, res) {
const file = files.uploadedFile;
if (file == undefined) {
res.writeHead(200, { "Content-Type": "text/plain" });
res.write("{ \"error\": \"Uploaded file not found\"}");
res.end();
return;
}
file.name = docManager.getCorrectName(file.name);
if (configServer.get('maxFileSize') < file.size || file.size <= 0) {
@ -388,6 +400,29 @@ app.post("/track", function (req, res) {
});
};
//checkjwt
if (cfgSignatureEnable && cfgSignatureUseForRequest) {
var checkJwtHeaderRes = documentService.checkJwtHeader(req);
if (checkJwtHeaderRes) {
if (checkJwtHeaderRes.payload) {
body = checkJwtHeaderRes.payload;
}
if (checkJwtHeaderRes.query) {
if (checkJwtHeaderRes.query.useraddress) {
userAddress = checkJwtHeaderRes.query.useraddress;
}
if (checkJwtHeaderRes.query.filename) {
fileName = fileUtility.getFileName(checkJwtHeaderRes.query.filename);
}
}
processTrack(res, body, fileName, userAddress);
} else {
res.write("{\"error\":1}");
res.end();
}
return;
}
if (req.body.hasOwnProperty("status")) {
processTrack(res, req.body, fileName, userAddress);
} else {
@ -465,23 +500,25 @@ app.get("/editor", function (req, res) {
name: fileName,
ext: fileUtility.getFileExtension(fileName, true),
uri: url,
version: countVersion
version: countVersion,
created: new Date().toDateString()
},
editor: {
type: type,
documentType: fileUtility.getFileType(fileName),
key: key,
token: "",
callbackUrl: docManager.getCallback(fileName),
isEdit: canEdit && mode != "review",
mode: canEdit && mode != "view" ? "edit" : "view",
canBackToFolder: type != "embedded",
getServerUrl: docManager.getServerUrl(),
getServerUrl: type == "embedded" ? null : "\"" + docManager.getServerUrl() + "\"",
curUserHostAddress: docManager.curUserHostAddress(),
lang: lang,
userid: userid,
name: name,
fileChoiceUrl: fileChoiceUrl,
plugins: plugins
plugins: JSON.stringify(plugins)
},
history: history,
setHistoryData: {
@ -490,7 +527,18 @@ app.get("/editor", function (req, res) {
}
};
res.render("editor", argss);
if (cfgSignatureEnable) {
app.render('config', argss, function(err, html){
if (err) {
console.log(err);
} else {
argss.editor.token = jwt.sign(JSON.parse("{"+html+"}"), cfgSignatureSecret, {expiresIn: cfgSignatureSecretExpiresIn});
}
res.render("editor", argss);
});
} else {
res.render("editor", argss);
}
}
catch (ex) {
console.log(ex);

View File

@ -30,7 +30,16 @@
"name": "/public",
"path": "public"
}
]
],
"token": {
"enable": false,
"useforrequest": true,
"algorithmRequest": "HS256",
"authorizationHeader": "Authorization",
"authorizationHeaderPrefix": "Bearer ",
"secret": "secret",
"expiresIn": "5m"
}
},
"plugins": {
"url": "",

View File

@ -24,12 +24,22 @@
*/
var path = require("path");
var urlModule = require("url");
var urllib = require("urllib");
var xml2js = require("xml2js");
var jwt = require("jsonwebtoken");
var jwa = require("jwa");
var fileUtility = require("./fileUtility");
var guidManager = require("./guidManager");
var configServer = require('config').get('server');
var siteUrl = configServer.get('siteUrl');
var cfgSignatureEnable = configServer.get('token.enable');
var cfgSignatureUseForRequest = configServer.get('token.useforrequest');
var cfgSignatureAuthorizationHeader = configServer.get('token.authorizationHeader');
var cfgSignatureAuthorizationHeaderPrefix = configServer.get('token.authorizationHeaderPrefix');
var cfgSignatureSecretExpiresIn = configServer.get('token.expiresIn');
var cfgSignatureSecret = configServer.get('token.secret');
var cfgSignatureSecretAlgorithmRequest = configServer.get('token.algorithmRequest');
var documentService = {};
@ -64,12 +74,19 @@ documentService.getConvertedUri = function (documentUri, fromExtension, toExtens
key: documentRevisionId
};
urllib.request(siteUrl + configServer.get('converterUrl'),
var uri = siteUrl + configServer.get('converterUrl');
var headers = {
'Content-Type': 'application/json'
};
if (cfgSignatureEnable && cfgSignatureUseForRequest) {
headers[cfgSignatureAuthorizationHeader] = cfgSignatureAuthorizationHeaderPrefix + this.fillJwtByUrl(uri, params);
}
urllib.request(uri,
{
method: "POST",
headers: {
'Content-Type': 'application/json'
},
headers: headers,
data: params
},
callback);
@ -79,15 +96,22 @@ documentService.getExternalUri = function (fileStream, contentLength, contentTyp
documentRevisionId = documentService.generateRevisionId(documentRevisionId);
var urlTostorage = siteUrl + configServer.get('storageUrl') + "?key=" + documentRevisionId;
var headers = {
"Content-Type": contentType == null ? "application/octet-stream" : contentType,
"Content-Length": contentLength.toString(),
"charset": "utf-8"
};
if (cfgSignatureEnable && cfgSignatureUseForRequest) {
const hmac = jwa(cfgSignatureSecretAlgorithmRequest);
var payloadhash = hmac.sign(fileStream, cfgSignatureSecret);
headers[cfgSignatureAuthorizationHeader] = cfgSignatureAuthorizationHeaderPrefix + this.fillJwtByUrl(urlTostorage, undefined, undefined, payloadhash);
}
urllib.request(urlTostorage,
{
method: "POST",
headers: {
"Content-Type": contentType == null ? "application/octet-stream" : contentType,
"Content-Length": contentLength.toString(),
"charset": "utf-8"
},
headers: headers,
data: fileStream
},
function (err, data) {
@ -116,10 +140,10 @@ documentService.processConvertServiceResponceError = function (errorCode) {
switch (errorCode) {
case -20:
errorMessage = errorMessageTemplate + "vkey deciphering error";
errorMessage = errorMessageTemplate + "Error encrypt signature";
break;
case -8:
errorMessage = errorMessageTemplate + "Error document VKey";
errorMessage = errorMessageTemplate + "Error document signature";
break;
case -7:
errorMessage = errorMessageTemplate + "Error document request";
@ -207,15 +231,43 @@ documentService.commandRequest = function (method, documentRevisionId, callback)
key: documentRevisionId
};
urllib.request(siteUrl + configServer.get('commandUrl'),
var uri = siteUrl + configServer.get('commandUrl');
var headers = {
'Content-Type': 'application/json'
};
if (cfgSignatureEnable && cfgSignatureUseForRequest) {
headers[cfgSignatureAuthorizationHeader] = cfgSignatureAuthorizationHeaderPrefix + this.fillJwtByUrl(uri, params);
}
urllib.request(uri,
{
method: "POST",
headers: {
'Content-Type': 'application/json'
},
headers: headers,
data: params
},
callback);
};
documentService.checkJwtHeader = function (req) {
var decoded = null;
var authorization = req.get(cfgSignatureAuthorizationHeader);
if (authorization && authorization.startsWith(cfgSignatureAuthorizationHeaderPrefix)) {
var token = authorization.substring(cfgSignatureAuthorizationHeaderPrefix.length);
try {
decoded = jwt.verify(token, cfgSignatureSecret);
} catch (err) {
console.log('checkJwtHeader error: name = ' + err.name + ' message = ' + err.message + ' token = ' + token)
}
}
return decoded;
}
documentService.fillJwtByUrl = function (uri, opt_dataObject, opt_iss, opt_payloadhash) {
var parseObject = urlModule.parse(uri, true);
var payload = {query: parseObject.query, payload: opt_dataObject, payloadhash: opt_payloadhash};
var options = {algorithm: cfgSignatureSecretAlgorithmRequest, expiresIn: cfgSignatureSecretExpiresIn, issuer: opt_iss};
return jwt.sign(payload, cfgSignatureSecret, options);
}
module.exports = documentService;

View File

@ -20,6 +20,8 @@
"ejs": "~2.5.1",
"express": "^4.14.1",
"formidable": "^1.1.1",
"jsonwebtoken": "^7.1.9",
"jwa": "^1.1.4",
"log4js": "^0.6.38",
"serve-favicon": "~2.3.0",
"sync-request": "^4.0.1",

View File

@ -0,0 +1,46 @@
"width": "100%",
"height": "100%",
"type": "<%= editor.type %>",
"documentType": "<%= editor.documentType %>",
"token": "<%= editor.token %>",
"document": {
"title": "<%= file.name %>",
"url": "<%= file.uri %>",
"fileType": "<%= file.ext %>",
"key": "<%= editor.key %>",
"info": {
"author": "Me",
"created": "<%= file.created %>"
},
"permissions": {
"download": true,
"edit": "<%= editor.isEdit %>",
"review": true
}
},
"editorConfig": {
"mode": "<%= editor.mode %>",
"lang": "<%= editor.lang %>",
"callbackUrl": "<%- editor.callbackUrl %>",
"user": {
"id": "<%= editor.userid %>",
"name": "<%= editor.name %>"
},
"embedded": {
"saveUrl": "<%= file.uri %>",
"embedUrl": "<%= file.uri %>",
"shareUrl": "<%= file.uri %>",
"toolbarDocked": "top"
},
"customization": {
"about": true,
"chat": true,
"comments": true,
"feedback": true,
"goback": {
"url": <%- editor.getServerUrl %>
}
},
"fileChoiceUrl": "<%= editor.fileChoiceUrl %>",
"plugins": <%- editor.plugins %>
}

View File

@ -44,8 +44,6 @@
<script type="text/javascript" language="javascript">
var docEditor;
var fileName = "<%= file.name %>";
var fileType = "<%= file.ext %>";
var innerAlert = function (message) {
if (console && console.log)
@ -102,53 +100,7 @@
var connectEditor = function () {
docEditor = new DocsAPI.DocEditor("iframeEditor",
{
width: "100%",
height: "100%",
type: "<%= editor.type %>",
documentType: "<%= editor.documentType %>",
document: {
title: fileName,
url: "<%= file.uri %>",
fileType: fileType,
key: "<%= editor.key %>",
info: {
author: "Me",
created: new Date().toDateString()
},
permissions: {
download: true,
edit: "<%= editor.isEdit %>" == "true",
review: true,
}
},
editorConfig: {
mode: "<%= editor.mode %>",
lang: "<%= editor.lang %>",
callbackUrl: "<%- editor.callbackUrl %>",
user: {
id: "<%= editor.userid %>",
name: "<%= editor.name %>",
},
embedded: {
saveUrl: "<%= file.uri %>",
embedUrl: "<%= file.uri %>",
shareUrl: "<%= file.uri %>",
toolbarDocked: "top"
},
customization: {
about: true,
chat: true,
comments: true,
feedback: true,
goback: {
url: "<%= editor.getServerUrl %>"
}
},
fileChoiceUrl: "<%= editor.fileChoiceUrl %>",
plugins: <%- JSON.stringify(editor.plugins) %>
},
docEditor = new DocsAPI.DocEditor("iframeEditor", {<% include config %>,
events: {
"onReady": onReady,
"onDocumentStateChange": onDocumentStateChange,