mirror of
https://github.com/ONLYOFFICE/server.git
synced 2026-04-07 14:04:35 +08:00
feat: split inbox secret into browser and request part
This commit is contained in:
@ -132,6 +132,7 @@
|
||||
"errorcode": 401
|
||||
},
|
||||
"secret": {
|
||||
"browser": {"string": "secret", "file": "", "tenants": {}},
|
||||
"inbox": {"string": "secret", "file": "", "tenants": {}},
|
||||
"outbox": {"string": "secret", "file": ""},
|
||||
"session": {"string": "secret", "file": ""}
|
||||
@ -144,6 +145,9 @@
|
||||
"outbox": false
|
||||
}
|
||||
},
|
||||
"browser": {
|
||||
"secretFromInbox": false
|
||||
},
|
||||
"inbox": {
|
||||
"header": "Authorization",
|
||||
"prefix": "Bearer "
|
||||
|
||||
@ -888,6 +888,12 @@ const c_oAscUrlTypes = {
|
||||
Session: 0,
|
||||
Temporary: 1
|
||||
};
|
||||
const c_oAscSecretType = {
|
||||
Browser: 0,
|
||||
Inbox: 1,
|
||||
Outbox: 2,
|
||||
Session: 3
|
||||
};
|
||||
|
||||
const buildVersion = '4.1.2';
|
||||
const buildNumber = 37;
|
||||
@ -909,5 +915,6 @@ exports.c_oAscUserAction = c_oAscUserAction;
|
||||
exports.c_oAscServerCommandErrors = c_oAscServerCommandErrors;
|
||||
exports.c_oAscForceSaveTypes = c_oAscForceSaveTypes;
|
||||
exports.c_oAscUrlTypes = c_oAscUrlTypes;
|
||||
exports.c_oAscSecretType = c_oAscSecretType;
|
||||
exports.buildVersion = buildVersion;
|
||||
exports.buildNumber = buildNumber;
|
||||
|
||||
@ -64,7 +64,6 @@ var cfgTokenOutboxHeader = config.get('services.CoAuthoring.token.outbox.header'
|
||||
var cfgTokenOutboxPrefix = config.get('services.CoAuthoring.token.outbox.prefix');
|
||||
var cfgTokenOutboxAlgorithm = config.get('services.CoAuthoring.token.outbox.algorithm');
|
||||
var cfgTokenOutboxExpires = config.get('services.CoAuthoring.token.outbox.expires');
|
||||
var cfgSignatureSecretInbox = config.get('services.CoAuthoring.secret.inbox');
|
||||
var cfgSignatureSecretOutbox = config.get('services.CoAuthoring.secret.outbox');
|
||||
var cfgVisibilityTimeout = config.get('queue.visibilityTimeout');
|
||||
var cfgQueueRetentionPeriod = config.get('queue.retentionPeriod');
|
||||
@ -84,7 +83,6 @@ var g_oIpFilterRules = function() {
|
||||
}
|
||||
return res;
|
||||
}();
|
||||
var isEmptySecretTenants = isEmptyObject(cfgSignatureSecretInbox.tenants);
|
||||
const pemfileCache = new NodeCache({stdTTL: ms(cfgExpPemStdTtl) / 1000, checkperiod: ms(cfgExpPemCheckPeriod) / 1000, errorOnMissing: false, useClones: true});
|
||||
|
||||
exports.CONVERTION_TIMEOUT = 1.5 * (cfgVisibilityTimeout + cfgQueueRetentionPeriod) * 1000;
|
||||
@ -700,9 +698,8 @@ function getSecretByElem(secretElem) {
|
||||
return secret;
|
||||
}
|
||||
exports.getSecretByElem = getSecretByElem;
|
||||
function getSecret(docId, opt_iss, opt_token) {
|
||||
var secretElem = cfgSignatureSecretInbox;
|
||||
if (!isEmptySecretTenants) {
|
||||
function getSecret(docId, secretElem, opt_iss, opt_token) {
|
||||
if (!isEmptyObject(secretElem.tenants)) {
|
||||
var iss;
|
||||
if (opt_token) {
|
||||
//look for issuer
|
||||
@ -714,7 +711,7 @@ function getSecret(docId, opt_iss, opt_token) {
|
||||
iss = opt_iss;
|
||||
}
|
||||
if (iss) {
|
||||
secretElem = cfgSignatureSecretInbox.tenants[iss];
|
||||
secretElem = secretElem.tenants[iss];
|
||||
if (!secretElem) {
|
||||
logger.error('getSecret unknown issuer: docId = %s iss = %s', docId, iss);
|
||||
}
|
||||
|
||||
@ -130,6 +130,9 @@ const cfgTokenSessionAlgorithm = config.get('token.session.algorithm');
|
||||
const cfgTokenSessionExpires = ms(config.get('token.session.expires'));
|
||||
const cfgTokenInboxHeader = config.get('token.inbox.header');
|
||||
const cfgTokenInboxPrefix = config.get('token.inbox.prefix');
|
||||
const cfgTokenBrowserSecretFromInbox = config.get('token.browser.secretFromInbox');
|
||||
const cfgSecretBrowser = config.get('secret.browser');
|
||||
const cfgSecretInbox = config.get('secret.inbox');
|
||||
const cfgSecretSession = config.get('secret.session');
|
||||
const cfgForceSaveEnable = config.get('autoAssembly.enable');
|
||||
const cfgForceSaveInterval = ms(config.get('autoAssembly.interval'));
|
||||
@ -1017,13 +1020,19 @@ function* _createSaveTimer(docId, opt_userId, opt_queue, opt_noDelay) {
|
||||
}
|
||||
}
|
||||
|
||||
function checkJwt(docId, token, isSession) {
|
||||
function checkJwt(docId, token, type) {
|
||||
var res = {decoded: null, description: null, code: null, token: token};
|
||||
var secret;
|
||||
if (isSession) {
|
||||
secret = utils.getSecretByElem(cfgSecretSession);
|
||||
} else {
|
||||
secret = utils.getSecret(docId, null, token);
|
||||
switch (type) {
|
||||
case commonDefines.c_oAscSecretType.Browser:
|
||||
secret = utils.getSecret(docId, cfgTokenBrowserSecretFromInbox ? cfgSecretInbox : cfgSecretBrowser, null, token);
|
||||
break;
|
||||
case commonDefines.c_oAscSecretType.Inbox:
|
||||
secret = utils.getSecret(docId, cfgSecretInbox, null, token);
|
||||
break;
|
||||
case commonDefines.c_oAscSecretType.Session:
|
||||
secret = utils.getSecretByElem(cfgSecretSession);
|
||||
break;
|
||||
}
|
||||
if (undefined == secret) {
|
||||
logger.error('empty secret: docId = %s token = %s', docId, token);
|
||||
@ -1047,7 +1056,7 @@ function checkJwtHeader(docId, req) {
|
||||
var authorization = req.get(cfgTokenInboxHeader);
|
||||
if (authorization && authorization.startsWith(cfgTokenInboxPrefix)) {
|
||||
var token = authorization.substring(cfgTokenInboxPrefix.length);
|
||||
return checkJwt(docId, token, false);
|
||||
return checkJwt(docId, token, commonDefines.c_oAscSecretType.Inbox);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -1056,7 +1065,7 @@ function checkJwtPayloadHash(docId, hash, body, token) {
|
||||
if (body && Buffer.isBuffer(body)) {
|
||||
var decoded = jwt.decode(token, {complete: true});
|
||||
var hmac = jwa(decoded.header.alg);
|
||||
var secret = utils.getSecret(docId, null, token);
|
||||
var secret = utils.getSecret(docId, cfgSecretInbox, null, token);
|
||||
var signature = hmac.sign(body, secret);
|
||||
res = (hash === signature);
|
||||
}
|
||||
@ -1178,8 +1187,9 @@ exports.install = function(server, callbackFunction) {
|
||||
conn.sessionTimeLastAction = new Date().getTime() - data.idletime;
|
||||
break;
|
||||
case 'refreshToken' :
|
||||
var isSession = !!data.jwtSession;
|
||||
var checkJwtRes = checkJwt(docId, data.jwtSession || data.jwtOpen, isSession);
|
||||
let secretType = !!data.jwtSession ? commonDefines.c_oAscSecretType.Session :
|
||||
commonDefines.c_oAscSecretType.Browser;
|
||||
var checkJwtRes = checkJwt(docId, data.jwtSession || data.jwtOpen, secretType);
|
||||
if (checkJwtRes.decoded) {
|
||||
if (checkJwtRes.decoded.document.key == conn.docId) {
|
||||
sendDataRefreshToken(conn, {token: fillJwtByConnection(conn), expires: cfgTokenSessionExpires});
|
||||
@ -1348,7 +1358,7 @@ exports.install = function(server, callbackFunction) {
|
||||
var docIdNew = cmd.getDocId();
|
||||
//check jwt
|
||||
if (cfgTokenEnableBrowser) {
|
||||
var checkJwtRes = checkJwt(docIdNew, cmd.getJwt(), false);
|
||||
var checkJwtRes = checkJwt(docIdNew, cmd.getJwt(), commonDefines.c_oAscSecretType.Browser);
|
||||
if (checkJwtRes.decoded) {
|
||||
fillVersionHistoryFromJwt(checkJwtRes.decoded, cmd);
|
||||
docIdNew = cmd.getDocId();
|
||||
@ -1841,8 +1851,9 @@ exports.install = function(server, callbackFunction) {
|
||||
let docId = data.docid;
|
||||
//check jwt
|
||||
if (cfgTokenEnableBrowser) {
|
||||
const isSession = !!data.jwtSession;
|
||||
const checkJwtRes = checkJwt(docId, data.jwtSession || data.jwtOpen, isSession);
|
||||
let secretType = !!data.jwtSession ? commonDefines.c_oAscSecretType.Session :
|
||||
commonDefines.c_oAscSecretType.Browser;
|
||||
const checkJwtRes = checkJwt(docId, data.jwtSession || data.jwtOpen, secretType);
|
||||
if (checkJwtRes.decoded) {
|
||||
if (!fillDataFromJwt(checkJwtRes.decoded, data)) {
|
||||
logger.warn("fillDataFromJwt return false: docId = %s", docId);
|
||||
|
||||
@ -923,7 +923,7 @@ exports.downloadAs = function(req, res) {
|
||||
|
||||
if (cfgTokenEnableBrowser) {
|
||||
var isValidJwt = false;
|
||||
var checkJwtRes = docsCoServer.checkJwt(docId, cmd.getJwt(), true);
|
||||
var checkJwtRes = docsCoServer.checkJwt(docId, cmd.getJwt(), commonDefines.c_oAscSecretType.Session);
|
||||
if (checkJwtRes.decoded) {
|
||||
var doc = checkJwtRes.decoded.document;
|
||||
if (!doc.permissions || (false !== doc.permissions.download || false !== doc.permissions.print)) {
|
||||
|
||||
@ -104,7 +104,7 @@ exports.uploadTempFile = function(req, res) {
|
||||
};
|
||||
function checkJwtUpload(docId, errorName, token){
|
||||
var res = {err: true, docId: null, userid: null};
|
||||
var checkJwtRes = docsCoServer.checkJwt(docId, token, true);
|
||||
var checkJwtRes = docsCoServer.checkJwt(docId, token, commonDefines.c_oAscSecretType.Session);
|
||||
if (checkJwtRes.decoded) {
|
||||
var doc = checkJwtRes.decoded.document;
|
||||
var edit = checkJwtRes.decoded.editorConfig;
|
||||
|
||||
Reference in New Issue
Block a user