mirror of
https://github.com/nodemailer/wildduck.git
synced 2024-09-20 15:26:03 +08:00
do not allow to use same TOTP code
This commit is contained in:
parent
af3649159c
commit
ecb74473a1
|
@ -98,5 +98,7 @@ module.exports = {
|
||||||
// access token default ttl in seconds (token ttl time is extended every time token is used by this value)
|
// access token default ttl in seconds (token ttl time is extended every time token is used by this value)
|
||||||
ACCESS_TOKEN_DEFAULT_TTL: 14 * 24 * 3600,
|
ACCESS_TOKEN_DEFAULT_TTL: 14 * 24 * 3600,
|
||||||
// access token can be extended until max lifetime value is reached in seconds
|
// access token can be extended until max lifetime value is reached in seconds
|
||||||
ACCESS_TOKEN_MAX_LIFETIME: 180 * 24 * 3600
|
ACCESS_TOKEN_MAX_LIFETIME: 180 * 24 * 3600,
|
||||||
|
|
||||||
|
TOTP_WINDOW_SIZE: 6
|
||||||
};
|
};
|
||||||
|
|
|
@ -1732,7 +1732,7 @@ class UserHandler {
|
||||||
secret,
|
secret,
|
||||||
encoding: 'base32',
|
encoding: 'base32',
|
||||||
token: data.token,
|
token: data.token,
|
||||||
window: 6
|
window: consts.TOTP_WINDOW_SIZE
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!verified) {
|
if (!verified) {
|
||||||
|
@ -1902,18 +1902,30 @@ class UserHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkTotp(user, data) {
|
async checkTotp(user, data) {
|
||||||
let userRlKey = 'totp:' + user;
|
let userRlKey = `totp:${user}`;
|
||||||
|
let totpSuccessKey = `totp:${user}:${data.token}`;
|
||||||
|
|
||||||
let rateLimitRes;
|
|
||||||
try {
|
try {
|
||||||
rateLimitRes = await this.rateLimit(userRlKey, data, 0);
|
let rateLimitRes = await this.rateLimit(userRlKey, data, 0);
|
||||||
|
if (!rateLimitRes.success) {
|
||||||
|
throw rateLimitResponse(rateLimitRes);
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
err.code = 'InternalDatabaseError';
|
err.code = err.code || 'InternalDatabaseError';
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rateLimitRes.success) {
|
try {
|
||||||
throw rateLimitResponse(rateLimitRes);
|
let totpAlreadyUsed = await this.redis.exists(totpSuccessKey);
|
||||||
|
if (totpAlreadyUsed) {
|
||||||
|
let err = new Error('This code has already been used, please try again with a new code');
|
||||||
|
err.response = 'NO';
|
||||||
|
err.code = 'RateLimitedError';
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
err.code = err.code || 'InternalDatabaseError';
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
let userData;
|
let userData;
|
||||||
|
@ -1971,7 +1983,7 @@ class UserHandler {
|
||||||
secret,
|
secret,
|
||||||
encoding: 'base32',
|
encoding: 'base32',
|
||||||
token: data.token,
|
token: data.token,
|
||||||
window: 6
|
window: consts.TOTP_WINDOW_SIZE
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -1995,6 +2007,18 @@ class UserHandler {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (verified) {
|
||||||
|
try {
|
||||||
|
await this.redis
|
||||||
|
.multi()
|
||||||
|
.set(totpSuccessKey, Date.now())
|
||||||
|
.expire(totpSuccessKey, consts.TOTP_WINDOW_SIZE * 30)
|
||||||
|
.exec();
|
||||||
|
} catch (err) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return verified;
|
return verified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue