diff --git a/CHANGES b/CHANGES index a0079d4fd..7ede77cc8 100644 --- a/CHANGES +++ b/CHANGES @@ -2174,4 +2174,5 @@ * oom: notification mails have links to dashboard * collectd: do not install xorg* packages * apptask: backup/restore tasks now use the backup memory limit configuration +* eventlog: add logout event diff --git a/src/eventlog.js b/src/eventlog.js index 4f6fdc2b2..c2e49fa43 100644 --- a/src/eventlog.js +++ b/src/eventlog.js @@ -1,11 +1,11 @@ 'use strict'; exports = module.exports = { - add: add, - get: get, - getAllPaged: getAllPaged, - getByCreationTime: getByCreationTime, - cleanup: cleanup, + add, + get, + getAllPaged, + getByCreationTime, + cleanup, // keep in sync with webadmin index.js filter ACTION_ACTIVATE: 'cloudron.activate', @@ -57,6 +57,7 @@ exports = module.exports = { ACTION_USER_ADD: 'user.add', ACTION_USER_LOGIN: 'user.login', + ACTION_USER_LOGOUT: 'user.logout', ACTION_USER_REMOVE: 'user.remove', ACTION_USER_UPDATE: 'user.update', ACTION_USER_TRANSFER: 'user.transfer', diff --git a/src/routes/accesscontrol.js b/src/routes/accesscontrol.js index e8e37ce0f..b38168344 100644 --- a/src/routes/accesscontrol.js +++ b/src/routes/accesscontrol.js @@ -1,11 +1,11 @@ 'use strict'; exports = module.exports = { - passwordAuth: passwordAuth, - tokenAuth: tokenAuth, + passwordAuth, + tokenAuth, - authorize: authorize, - websocketAuth: websocketAuth + authorize, + websocketAuth }; var accesscontrol = require('../accesscontrol.js'), @@ -99,6 +99,7 @@ function tokenAuth(req, res, next) { if (error && error.reason === BoxError.INVALID_CREDENTIALS) return next(new HttpError(401, 'Unauthorized')); if (error) return next(new HttpError(500, error.message)); + req.access_token = token; // used in logout route req.user = user; next(); diff --git a/src/routes/cloudron.js b/src/routes/cloudron.js index 5ec867ae3..9080548a9 100644 --- a/src/routes/cloudron.js +++ b/src/routes/cloudron.js @@ -64,24 +64,11 @@ function login(req, res, next) { } function logout(req, res) { - var token; + assert.strictEqual(typeof req.access_token, 'string'); - // this determines the priority - if (req.body && req.body.access_token) token = req.body.access_token; - if (req.query && req.query.access_token) token = req.query.access_token; - if (req.headers && req.headers.authorization) { - var parts = req.headers.authorization.split(' '); - if (parts.length == 2) { - var scheme = parts[0]; - var credentials = parts[1]; + eventlog.add(eventlog.ACTION_USER_LOGOUT, auditSource.fromRequest(req), { userId: req.user.id, user: users.removePrivateFields(req.user) }); - if (/^Bearer$/i.test(scheme)) token = credentials; - } - } - - if (!token) return res.redirect('/login.html'); - - tokendb.delByAccessToken(token, function () { res.redirect('/login.html'); }); + tokendb.delByAccessToken(req.access_token, function () { res.redirect('/login.html'); }); } function passwordResetRequest(req, res, next) { diff --git a/src/server.js b/src/server.js index f2f297082..4be30b9b3 100644 --- a/src/server.js +++ b/src/server.js @@ -95,10 +95,10 @@ function initializeExpressSync() { // login/logout routes router.post('/api/v1/cloudron/login', json, password, routes.cloudron.login); - router.get ('/api/v1/cloudron/logout', routes.cloudron.logout); // this will invalidate the token if any and redirect to /login.html always - router.post('/api/v1/cloudron/password_reset_request', json, routes.cloudron.passwordResetRequest); - router.post('/api/v1/cloudron/password_reset', json, routes.cloudron.passwordReset); - router.post('/api/v1/cloudron/setup_account', json, routes.cloudron.setupAccount); + router.get ('/api/v1/cloudron/logout', token, routes.cloudron.logout); // this will invalidate the token if any and redirect to /login.html always + router.post('/api/v1/cloudron/password_reset_request', json, routes.cloudron.passwordResetRequest); + router.post('/api/v1/cloudron/password_reset', json, routes.cloudron.passwordReset); + router.post('/api/v1/cloudron/setup_account', json, routes.cloudron.setupAccount); // developer routes router.post('/api/v1/developer/login', json, password, routes.cloudron.login); // DEPRECATED we should use the regular /api/v1/cloudron/login