diff --git a/src/users.js b/src/users.js index 4010923bf..7f220bfbf 100644 --- a/src/users.js +++ b/src/users.js @@ -59,6 +59,8 @@ const ORDERED_ROLES = [ exports.ROLE_USER, exports.ROLE_USER_MANAGER, exports.RO const USERS_FIELDS = [ 'id', 'username', 'email', 'fallbackEmail', 'password', 'salt', 'creationTime', 'resetToken', 'displayName', 'twoFactorAuthenticationEnabled', 'twoFactorAuthenticationSecret', 'active', 'source', 'role', 'resetTokenCreationTime', 'loginLocationsJson' ].join(','); +const GHOST_LIFETIME = 6 * 60 * 60 * 1000; // 6 hours + const appPasswords = require('./apppasswords.js'), assert = require('assert'), BoxError = require('./boxerror.js'), @@ -250,10 +252,26 @@ function verifyGhost(username, password) { var ghostData = safe.JSON.parse(safe.fs.readFileSync(paths.GHOST_USER_FILE, 'utf8')); if (!ghostData) return false; - if (username in ghostData && ghostData[username] === password) { - debug('verifyGhost: matched ghost user'); - safe.fs.unlinkSync(paths.GHOST_USER_FILE); - return true; + // either the username is an object with { password, expiresAt } or a string with the password which will expire on first match + if (username in ghostData) { + if (typeof ghostData[username] === 'object') { + if (ghostData[username].expiresAt < Date.now()) { + debug('verifyGhost: password expired'); + delete ghostData[username]; + safe.fs.writeFileSync(paths.GHOST_USER_FILE, JSON.stringify(ghostData, null, 4), 'utf8'); + return false; + } else if (ghostData[username].password === password) { + debug('verifyGhost: matched ghost user'); + return true; + } else { + return false; + } + } else if(ghostData[username] === password) { + debug('verifyGhost: matched ghost user'); + delete ghostData[username]; + safe.fs.writeFileSync(paths.GHOST_USER_FILE, JSON.stringify(ghostData, null, 4), 'utf8'); + return true; + } } return false;