const { Model } = require('flitter-orm') const speakeasy = require('speakeasy') const MFARecoveryCode = require('./MFARecoveryCode.model') const uuid = require('uuid').v4 class MFATokenModel extends Model { static get services() { return [...super.services, 'MFA'] } static get schema() { return { secret: String, otpauth_url: String, recovery_codes: [MFARecoveryCode], } } async attempt_recovery(code) { for ( const token of this.recovery_codes ) { if ( await token.verify(code) && !token.used ) { token.used = true return true } } return false } async generate_recovery() { this.recovery_codes = [] const values = [] for ( let i = 0; i < 4; i++ ) { const value = uuid() values.push(value) this.recovery_codes.push(await MFARecoveryCode.create(value)) } return values } verify(value) { return speakeasy.totp.verify({ secret: this.secret, encoding: 'base32', token: value, }) } } module.exports = exports = MFATokenModel