2015-10-09 11:37:17 +02:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
exports = module.exports = {
|
2015-10-11 13:22:52 +02:00
|
|
|
start: start,
|
|
|
|
|
stop: stop
|
2015-10-09 11:37:17 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var assert = require('assert'),
|
|
|
|
|
debug = require('debug')('box:simpleauth'),
|
|
|
|
|
user = require('./user.js'),
|
|
|
|
|
tokendb = require('./tokendb.js'),
|
2015-10-11 13:22:52 +02:00
|
|
|
clients = require('./clients.js'),
|
|
|
|
|
config = require('./config.js'),
|
|
|
|
|
debug = require('debug')('box:proxy'),
|
|
|
|
|
middleware = require('./middleware'),
|
|
|
|
|
express = require('express'),
|
|
|
|
|
HttpError = require('connect-lastmile').HttpError,
|
|
|
|
|
HttpSuccess = require('connect-lastmile').HttpSuccess,
|
|
|
|
|
DatabaseError = require('./databaseerror.js'),
|
|
|
|
|
UserError = require('./user.js').UserError,
|
|
|
|
|
http = require('http');
|
2015-10-09 11:37:17 +02:00
|
|
|
|
2015-10-11 13:22:52 +02:00
|
|
|
var gHttpServer = null;
|
|
|
|
|
|
|
|
|
|
function loginLogic(clientId, username, password, callback) {
|
2015-10-09 11:37:17 +02:00
|
|
|
assert.strictEqual(typeof clientId, 'string');
|
|
|
|
|
assert.strictEqual(typeof username, 'string');
|
|
|
|
|
assert.strictEqual(typeof password, 'string');
|
|
|
|
|
assert.strictEqual(typeof callback, 'function');
|
|
|
|
|
|
|
|
|
|
debug('login: client %s and user %s', clientId, username);
|
|
|
|
|
|
2015-10-09 16:52:46 +02:00
|
|
|
clients.get(clientId, function (error, clientObject) {
|
2015-10-09 11:37:17 +02:00
|
|
|
if (error) return callback(error);
|
|
|
|
|
|
|
|
|
|
user.verify(username, password, function (error, userObject) {
|
|
|
|
|
if (error) return callback(error);
|
|
|
|
|
|
|
|
|
|
var accessToken = tokendb.generateToken();
|
|
|
|
|
var expires = Date.now() + 24 * 60 * 60 * 1000; // 1 day
|
|
|
|
|
|
|
|
|
|
tokendb.add(accessToken, tokendb.PREFIX_USER + userObject.id, clientId, expires, clientObject.scope, function (error) {
|
|
|
|
|
if (error) return callback(error);
|
|
|
|
|
|
|
|
|
|
debug('login: new access token for client %s and user %s: %s', clientId, username, accessToken);
|
|
|
|
|
|
|
|
|
|
callback(null, { accessToken: accessToken, user: userObject });
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-11 13:22:52 +02:00
|
|
|
function logoutLogic(accessToken, callback) {
|
2015-10-09 11:37:17 +02:00
|
|
|
assert.strictEqual(typeof accessToken, 'string');
|
|
|
|
|
assert.strictEqual(typeof callback, 'function');
|
|
|
|
|
|
|
|
|
|
debug('logout: %s', accessToken);
|
|
|
|
|
|
|
|
|
|
tokendb.del(accessToken, function (error) {
|
|
|
|
|
if (error) return callback(error);
|
|
|
|
|
callback(null);
|
|
|
|
|
});
|
|
|
|
|
}
|
2015-10-11 13:22:52 +02:00
|
|
|
|
|
|
|
|
function login(req, res, next) {
|
|
|
|
|
assert.strictEqual(typeof req.body, 'object');
|
|
|
|
|
|
|
|
|
|
if (typeof req.body.clientId !== 'string') return next(new HttpError(400, 'clientId is required'));
|
|
|
|
|
if (typeof req.body.username !== 'string') return next(new HttpError(400, 'username is required'));
|
|
|
|
|
if (typeof req.body.password !== 'string') return next(new HttpError(400, 'password is required'));
|
|
|
|
|
|
|
|
|
|
loginLogic(req.body.clientId, req.body.username, req.body.password, function (error, result) {
|
|
|
|
|
if (error && error.reason === DatabaseError.NOT_FOUND) return next(new HttpError(401, 'Unknown client'));
|
|
|
|
|
if (error && error.reason === UserError.NOT_FOUND) return next(new HttpError(401, 'Forbidden'));
|
|
|
|
|
if (error && error.reason === UserError.WRONG_PASSWORD) return next(new HttpError(401, 'Forbidden'));
|
|
|
|
|
if (error) return next(new HttpError(500, error));
|
|
|
|
|
|
|
|
|
|
var tmp = {
|
|
|
|
|
accessToken: result.accessToken,
|
|
|
|
|
user: {
|
|
|
|
|
id: result.user.id,
|
|
|
|
|
username: result.user.username,
|
|
|
|
|
email: result.user.email,
|
|
|
|
|
admin: !!result.user.admin
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
next(new HttpSuccess(201, tmp));
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function logout(req, res, next) {
|
2015-10-11 13:29:23 +02:00
|
|
|
assert.strictEqual(typeof req.query, 'object');
|
2015-10-11 13:22:52 +02:00
|
|
|
|
2015-10-11 13:29:23 +02:00
|
|
|
if (typeof req.query.access_token !== 'string') return next(new HttpError(400, 'access_token in query required'));
|
2015-10-11 13:22:52 +02:00
|
|
|
|
2015-10-11 13:29:23 +02:00
|
|
|
logoutLogic(req.query.access_token, function (error) {
|
|
|
|
|
if (error && error.reason === DatabaseError.NOT_FOUND) return next(new HttpError(401, 'Forbidden'));
|
2015-10-11 13:22:52 +02:00
|
|
|
if (error) return next(new HttpError(500, error));
|
|
|
|
|
|
|
|
|
|
next(new HttpSuccess(200, {}));
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function initializeExpressSync() {
|
|
|
|
|
var app = express();
|
|
|
|
|
var httpServer = http.createServer(app);
|
|
|
|
|
|
|
|
|
|
httpServer.on('error', console.error);
|
|
|
|
|
|
|
|
|
|
var json = middleware.json({ strict: true, limit: '100kb' });
|
|
|
|
|
var router = new express.Router();
|
|
|
|
|
|
|
|
|
|
// basic auth
|
|
|
|
|
router.post('/api/v1/login', login);
|
|
|
|
|
router.get ('/api/v1/logout', logout);
|
|
|
|
|
|
|
|
|
|
app
|
|
|
|
|
.use(middleware.timeout(10000))
|
|
|
|
|
.use(json)
|
2015-10-11 13:29:23 +02:00
|
|
|
.use(router)
|
|
|
|
|
.use(middleware.lastMile());
|
2015-10-11 13:22:52 +02:00
|
|
|
|
|
|
|
|
return httpServer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function start(callback) {
|
|
|
|
|
assert.strictEqual(typeof callback, 'function');
|
|
|
|
|
|
|
|
|
|
gHttpServer = initializeExpressSync();
|
|
|
|
|
gHttpServer.listen(config.get('simpleAuthPort'), '127.0.0.1', callback);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function stop(callback) {
|
|
|
|
|
assert.strictEqual(typeof callback, 'function');
|
|
|
|
|
|
|
|
|
|
gHttpServer.close(callback);
|
|
|
|
|
}
|