Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/actions/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const globalLoginAttempts = async (ctx) => {
// globally scoped go next
if (globalAttempts > ctx.globalLockAfterAttempts) {
const duration = moment().add(config.keepGlobalLoginAttempts, 'seconds').toNow(true);
const msg = `You are locked from making login attempts for the next ${duration}`;
const msg = `You are locked from making login attempts for the next ${duration} from ipaddress '${ctx.remoteip}'`;
throw new Errors.HttpStatusError(429, msg);
}
};
Expand All @@ -70,7 +70,7 @@ const localLoginAttempts = async (ctx, data) => {
// locally scoped login attempts are prioritized
if (scopeAttempts > ctx.lockAfterAttempts) {
const duration = moment().add(config.keepLoginAttempts, 'seconds').toNow(true);
const msg = `You are locked from making login attempts for the next ${duration}`;
const msg = `You are locked from making login attempts for the next ${duration} from ipaddress '${ctx.remoteip}'`;
throw new Errors.HttpStatusError(429, msg);
}
};
Expand Down
8 changes: 4 additions & 4 deletions src/utils/challenges/challenge.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const partial = require('lodash/partial');
const moment = require('moment');
const { HttpStatusError } = require('common-errors');
const generateEmail = require('./email/generate.js');
const {
Expand All @@ -7,9 +8,6 @@ const {
} = require('../../constants.js');
const sendSms = require('./phone/send');

// eslint-disable-next-line max-len
const isThrottled = new HttpStatusError(429, 'We\'ve already sent you an email, if it doesn\'t come - please try again in a little while or send us an email');

// contains challenges
const CHALLENGES = {

Expand All @@ -36,7 +34,9 @@ async function generateChallenge(type, opts, ctx = {}, wait = false) {
ctx.token = token;
} catch (error) {
if (error.message === '429') {
throw isThrottled;
const duration = moment().add(opts.ttl, 'seconds').toNow(true);
const msg = `We've already sent you an email, if it doesn't come - please try again in ${duration} or send us an email`;
throw new HttpStatusError(429, msg);
}

throw error;
Expand Down
2 changes: 1 addition & 1 deletion src/utils/checkIpLimits.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ module.exports = async function checkLimits(redis, registrationLimits, ipaddress

const cardinality = props[3];
if (cardinality > times) {
const msg = 'You can\'t register more users from your ipaddress now';
const msg = `You can't register more users from your ipaddress '${ipaddress}' now`;
throw new HttpStatusError(429, msg);
}

Expand Down
6 changes: 6 additions & 0 deletions test/suites/challenge.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ describe('#challenge', function challengeSuite() {
});

it('must fail to send challenge email more than once in an hour per user', function test() {
const msg = 'We\'ve already sent you an email, if it doesn\'t come - please try again in 4 hours or send us an email';

return Promise.bind(this)
.then(requestChallenge)
.then(requestChallenge)
Expand All @@ -77,10 +79,13 @@ describe('#challenge', function challengeSuite() {
.then((validation) => {
expect(validation.name).to.be.eq('HttpStatusError');
expect(validation.statusCode).to.be.eq(429);
expect(validation.message).to.be.eq(msg);
});
});

it('must fail to send challeng email during race condition', function test() {
const msg = 'We\'ve already sent you an email, if it doesn\'t come - please try again in 4 hours or send us an email';

return Promise
.bind(this)
.return([requestChallenge, requestChallenge, requestChallenge])
Expand All @@ -90,6 +95,7 @@ describe('#challenge', function challengeSuite() {
.then((validation) => {
expect(validation.name).to.be.eq('HttpStatusError');
expect(validation.statusCode).to.be.eq(429);
expect(validation.message).to.be.eq(msg);
});
});
});
Expand Down
6 changes: 6 additions & 0 deletions test/suites/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ describe('#login', function loginSuite() {
it('must lock account for authentication after 5 invalid login attemps', () => {
const userWithRemoteIP = { remoteip: '10.0.0.1', ...user };
const promises = [];
const eMsg = 'You are locked from making login attempts for the next 2 hours from ipaddress \'10.0.0.1\'';

times(5, () => {
promises.push((
Expand All @@ -139,6 +140,7 @@ describe('#login', function loginSuite() {
.then((login) => {
expect(login.name).to.be.eq('HttpStatusError');
expect(login.statusCode).to.be.eq(429);
expect(login.message).to.be.eq(eMsg);
})
));

Expand All @@ -148,6 +150,7 @@ describe('#login', function loginSuite() {
it('must lock ip for login completely after 15 attempts', async () => {
const userWithRemoteIP = { remoteip: '10.0.0.1', ...user, username: 'doesnt_exist' };
const promises = [];
const eMsg = 'You are locked from making login attempts for the next 7 days from ipaddress \'10.0.0.1\'';

times(16, () => {
promises.push((
Expand All @@ -164,6 +167,9 @@ describe('#login', function loginSuite() {

expect(Http404.length).to.be.eq(15);
expect(Http429.length).to.be.eq(1);

const Http429Error = Http429[0];
expect(Http429Error.message).to.be.eq(eMsg);
});

it('should reject signing in with bogus or expired disposable password', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/suites/register.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ describe('#register', function registerSuite() {
.then((failed) => {
assert.equal(failed.name, 'HttpStatusError');
assert.equal(failed.statusCode, 429);
assert.equal(failed.message, 'You can\'t register more users from your ipaddress now');
assert.equal(failed.message, 'You can\'t register more users from your ipaddress \'192.168.1.1\' now');
});
});
});
Expand Down