Support MFA recovery tokens
This commit is contained in:
23
app/models/auth/MFARecoveryCode.model.js
Normal file
23
app/models/auth/MFARecoveryCode.model.js
Normal file
@@ -0,0 +1,23 @@
|
||||
const { Model } = require('flitter-orm')
|
||||
const bcrypt = require('bcrypt')
|
||||
|
||||
class MFARecoveryCodeModel extends Model {
|
||||
static get schema() {
|
||||
return {
|
||||
code: String,
|
||||
used: { type: Boolean, default: false },
|
||||
generated: { type: Date, default: () => new Date },
|
||||
}
|
||||
}
|
||||
|
||||
static async create(value) {
|
||||
const code = await bcrypt.hash(value, 10)
|
||||
return new this({ code })
|
||||
}
|
||||
|
||||
async verify(code) {
|
||||
return await bcrypt.compare(code, this.code)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = exports = MFARecoveryCodeModel
|
||||
@@ -1,5 +1,7 @@
|
||||
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() {
|
||||
@@ -10,9 +12,34 @@ class MFATokenModel extends Model {
|
||||
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,
|
||||
|
||||
Reference in New Issue
Block a user