From ecac40d062747e4668dd942443b361077fd55f74 Mon Sep 17 00:00:00 2001 From: Egil Moeller Date: Thu, 19 Apr 2012 16:04:03 +0200 Subject: [PATCH] Changed the authentication mechanism to support hooks --- settings.json.template | 13 +++++---- src/node/hooks/express/adminplugins.js | 2 +- src/node/hooks/express/webaccess.js | 39 ++++++++++++++++---------- src/node/server.js | 5 ++-- 4 files changed, 35 insertions(+), 24 deletions(-) diff --git a/settings.json.template b/settings.json.template index d8f67e765..f89fcd8ed 100644 --- a/settings.json.template +++ b/settings.json.template @@ -51,22 +51,23 @@ Note: /admin always requires authentication. */ "requireAuthentication": false, - /* Require authorization by a module, or a user with is_admin set, - see below. Access to /admin allways requires either, regardless - of this setting. */ + /* Require authorization by a module, or a user with is_admin set, see below. */ "requireAuthorization": false, - /* Users for basic authentication. is_admin = true gives access to /admin */ + /* Users for basic authentication. is_admin = true gives access to /admin. + If you do not uncomment this, /admin will not be available! */ + /* "users": { "admin": { - "password": "changeme", + "password": "changeme1", "is_admin": true }, "user": { - "password": "changeme", + "password": "changeme1", "is_admin": false } }, + */ /* The log level we are using, can be: DEBUG, INFO, WARN, ERROR */ "loglevel": "INFO" diff --git a/src/node/hooks/express/adminplugins.js b/src/node/hooks/express/adminplugins.js index 6cc80cf2a..7b21206c9 100644 --- a/src/node/hooks/express/adminplugins.js +++ b/src/node/hooks/express/adminplugins.js @@ -21,7 +21,7 @@ exports.expressCreateServer = function (hook_name, args, cb) { exports.socketio = function (hook_name, args, cb) { var io = args.io.of("/pluginfw/installer"); io.on('connection', function (socket) { - if (!socket.handshake.session.user.is_admin) return; + if (!socket.handshake.session.user || !socket.handshake.session.user.is_admin) return; socket.on("load", function (query) { socket.emit("installed-results", {results: plugins.plugins}); diff --git a/src/node/hooks/express/webaccess.js b/src/node/hooks/express/webaccess.js index 499451d89..028d8ab1b 100644 --- a/src/node/hooks/express/webaccess.js +++ b/src/node/hooks/express/webaccess.js @@ -8,7 +8,13 @@ var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks'); //checks for basic http auth exports.basicAuth = function (req, res, next) { - var authorize = function (cb) { + var hookResultMangle = function (cb) { + return function (err, data) { + return cb(!err && data.length && data[0]); + } + } + + var authorize = function (cb) { // Do not require auth for static paths...this could be a bit brittle if (req.path.match(/^\/(static|javascripts|pluginfw)/)) return cb(true); @@ -19,8 +25,7 @@ exports.basicAuth = function (req, res, next) { if (req.session && req.session.user && req.session.user.is_admin) return cb(true); - // hooks.aCallFirst("authorize", {resource: req.path, req: req}, cb); - cb(false); + hooks.aCallFirst("authorize", {req: req, res:res, next:next, resource: req.path}, hookResultMangle(cb)); } var authenticate = function (cb) { @@ -35,24 +40,28 @@ exports.basicAuth = function (req, res, next) { req.session.user = settings.users[username]; return cb(true); } - // return hooks.aCallFirst("authenticate", {req: req, username: username, password: password}, cb); + return hooks.aCallFirst("authenticate", {req: req, res:res, next:next, username: username, password: password}, hookResultMangle(cb)); } - // hooks.aCallFirst("authenticate", {req: req}, cb); - cb(false); + hooks.aCallFirst("authenticate", {req: req, res:res, next:next}, hookResultMangle(cb)); } + /* Authentication OR authorization failed. */ var failure = function () { - /* Authentication OR authorization failed. Return Auth required - * Headers, delayed for 1 second, if authentication failed. */ - res.header('WWW-Authenticate', 'Basic realm="Protected Area"'); - if (req.headers.authorization) { - setTimeout(function () { + return hooks.aCallFirst("authFailure", {req: req, res:res, next:next}, hookResultMangle(function (ok) { + if (ok) return; + /* No plugin handler for invalid auth. Return Auth required + * Headers, delayed for 1 second, if authentication failed + * before. */ + res.header('WWW-Authenticate', 'Basic realm="Protected Area"'); + if (req.headers.authorization) { + setTimeout(function () { + res.send('Authentication required', 401); + }, 1000); + } else { res.send('Authentication required', 401); - }, 1000); - } else { - res.send('Authentication required', 401); - } + } + })); } diff --git a/src/node/server.js b/src/node/server.js index 6b443edb7..9d2c52e44 100644 --- a/src/node/server.js +++ b/src/node/server.js @@ -30,6 +30,7 @@ var path = require('path'); var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins"); var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks"); var npm = require("npm/lib/npm.js"); +var _ = require("underscore"); //try to get the git version var version = ""; @@ -88,11 +89,11 @@ async.waterfall([ //let the server listen app.listen(settings.port, settings.ip); console.log("Server is listening at " + settings.ip + ":" + settings.port); - if(settings.adminHttpAuth){ + if(!_.isEmpty(settings.users)){ console.log("Plugin admin page listening at " + settings.ip + ":" + settings.port + "/admin/plugins"); } else{ - console.log("Admin username and password not set in settings.json. To access admin please uncomment and edit adminHttpAuth in settings.json"); + console.log("Admin username and password not set in settings.json. To access admin please uncomment and edit 'users' in settings.json"); } callback(null); }