Add app passwords feature

This commit is contained in:
Girish Ramakrishnan
2020-01-31 15:28:42 -08:00
parent e3878fa381
commit 3427db3983
17 changed files with 459 additions and 58 deletions
+2 -2
View File
@@ -61,7 +61,7 @@ function initialize(callback) {
}
if (username.indexOf('@') === -1) {
users.verifyWithUsername(username, password, function (error, result) {
users.verifyWithUsername(username, password, users.AP_WEBADMIN, function (error, result) {
if (error && error.reason === BoxError.NOT_FOUND) return createAndVerifyUserIfNotExist(username, password, callback);
if (error && error.reason === BoxError.INVALID_CREDENTIALS) return callback(null, false);
if (error) return callback(error);
@@ -69,7 +69,7 @@ function initialize(callback) {
callback(null, result);
});
} else {
users.verifyWithEmail(username, password, function (error, result) {
users.verifyWithEmail(username, password, users.AP_WEBADMIN, function (error, result) {
if (error && error.reason === BoxError.NOT_FOUND) return createAndVerifyUserIfNotExist(username, password, callback);
if (error && error.reason === BoxError.INVALID_CREDENTIALS) return callback(null, false);
if (error) return callback(error);
+60
View File
@@ -0,0 +1,60 @@
'use strict';
exports = module.exports = {
list: list,
get: get,
del: del,
add: add
};
var assert = require('assert'),
BoxError = require('../boxerror.js'),
HttpError = require('connect-lastmile').HttpError,
HttpSuccess = require('connect-lastmile').HttpSuccess,
users = require('../users.js');
function get(req, res, next) {
assert.strictEqual(typeof req.user, 'object');
assert.strictEqual(typeof req.params.id, 'string');
users.getAppPassword(req.params.id, function (error, result) {
if (error) return next(BoxError.toHttpError(error));
next(new HttpSuccess(200, result));
});
}
function add(req, res, next) {
assert.strictEqual(typeof req.user, 'object');
assert.strictEqual(typeof req.body, 'object');
if (typeof req.body.name !== 'string') return next(new HttpError(400, 'name must be string'));
if (typeof req.body.identifier !== 'string') return next(new HttpError(400, 'identifier must be string'));
users.addAppPassword(req.user.id, req.body.identifier, req.body.name, function (error, result) {
if (error) return next(BoxError.toHttpError(error));
next(new HttpSuccess(200, result));
});
}
function list(req, res, next) {
assert.strictEqual(typeof req.user, 'object');
users.getAppPasswords(req.user.id, function (error, result) {
if (error) return next(BoxError.toHttpError(error));
next(new HttpSuccess(200, result));
});
}
function del(req, res, next) {
assert.strictEqual(typeof req.user, 'object');
assert.strictEqual(typeof req.params.id, 'string');
users.delAppPassword(req.params.id, function (error) {
if (error) return next(BoxError.toHttpError(error));
next(new HttpSuccess(204, {}));
});
}
+1 -1
View File
@@ -17,7 +17,7 @@ function login(req, res, next) {
var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress || null;
if (!user.ghost && user.twoFactorAuthenticationEnabled) {
if (!user.ghost && !user.appPassword && user.twoFactorAuthenticationEnabled) {
if (!req.body.totpToken) return next(new HttpError(401, 'A totpToken must be provided'));
let verified = speakeasy.totp.verify({ secret: user.twoFactorAuthenticationSecret, encoding: 'base32', token: req.body.totpToken, window: 2 });
+1
View File
@@ -2,6 +2,7 @@
exports = module.exports = {
accesscontrol: require('./accesscontrol.js'),
appPasswords: require('./apppasswords.js'),
apps: require('./apps.js'),
appstore: require('./appstore.js'),
backups: require('./backups.js'),
+1 -1
View File
@@ -257,7 +257,7 @@ function login(req, res) {
})(req, res, function (error) {
if (error) return res.redirect('/api/v1/session/login?' + failureQuery); // on some exception in the handlers
if (!req.user.ghost && req.user.twoFactorAuthenticationEnabled) {
if (!req.user.ghost && !req.user.appPassword && req.user.twoFactorAuthenticationEnabled) {
if (!req.body.totpToken) {
let failureQuery = querystring.stringify({ error: 'A 2FA token is required', returnTo: returnTo });
return res.redirect('/api/v1/session/login?' + failureQuery);
+1 -1
View File
@@ -723,7 +723,7 @@ describe('Users API', function () {
});
it('did change the user password', function (done) {
users.verify(user_0.id, 'bigenough', function (error) {
users.verify(user_0.id, 'bigenough', users.AP_WEBADMIN, function (error) {
expect(error).to.be(null);
done();
});
+1 -1
View File
@@ -112,7 +112,7 @@ function verifyPassword(req, res, next) {
if (typeof req.body.password !== 'string') return next(new HttpError(400, 'API call requires user password'));
users.verifyWithUsername(req.user.username, req.body.password, function (error) {
users.verifyWithUsername(req.user.username, req.body.password, users.AP_WEBADMIN, function (error) {
if (error) return next(BoxError.toHttpError(error));
req.body.password = '<redacted>'; // this will prevent logs from displaying plain text password