(userId, methodId, token)
| 318 | } |
| 319 | |
| 320 | async validate2FaLogin(userId, methodId, token) { |
| 321 | const user2FA = await db.User2fa.findByPk(methodId); |
| 322 | |
| 323 | if (`${user2FA.user_id}` !== `${userId}`) { |
| 324 | return new Promise((resolve, reject) => reject({ error: "User mismatch" })); |
| 325 | } |
| 326 | |
| 327 | if (!user2FA) { |
| 328 | return new Promise((resolve, reject) => reject({ error: "2FA method does not exist" })); |
| 329 | } |
| 330 | |
| 331 | const totp = new TOTP({ |
| 332 | secret: user2FA.secret |
| 333 | }); |
| 334 | |
| 335 | const delta = totp.validate({ token, window: 1 }); |
| 336 | if (delta !== null) { |
| 337 | const foundUser = await db.User.findOne({ where: { id: user2FA.user_id } }); |
| 338 | return foundUser; |
| 339 | } |
| 340 | |
| 341 | // Avoid triggering the model getter when backup is null (getter decrypts the value) |
| 342 | if (user2FA.getDataValue("backup")) { |
| 343 | try { |
| 344 | const backupCodes = JSON.parse(user2FA.backup); |
| 345 | if (backupCodes.includes(token)) { |
| 346 | const foundUser = await db.User.findOne({ where: { id: user2FA.user_id } }); |
| 347 | if (foundUser) { |
| 348 | const newBackupCodes = backupCodes.filter((code) => code !== token); |
| 349 | await user2FA.update({ backup: JSON.stringify(newBackupCodes) }); |
| 350 | return foundUser; |
| 351 | } |
| 352 | } |
| 353 | } catch (e) { |
| 354 | // do nothing |
| 355 | } |
| 356 | } |
| 357 | |
| 358 | return new Promise((resolve, reject) => reject(new Error(401))); |
| 359 | } |
| 360 | |
| 361 | findAll() { |
| 362 | return db.User.findAll({ |
no test coverage detected