Support MFA recovery tokens
This commit is contained in:
@@ -84,6 +84,41 @@ class AuthController extends Controller {
|
||||
return res.api(await user.to_api())
|
||||
}
|
||||
|
||||
async attempt_mfa_recovery(req, res, next) {
|
||||
if (
|
||||
!req.user.mfa_enabled
|
||||
|| !Array.isArray(req.user.mfa_token.recovery_codes)
|
||||
|| req.user.mfa_token.recovery_codes.length < 1
|
||||
)
|
||||
return res.status(400)
|
||||
.message('Your user is not configured to use MFA, or has no recovery codes.')
|
||||
.api()
|
||||
|
||||
if ( !req.body.code )
|
||||
return res.status(400)
|
||||
.message('Missing required field: code')
|
||||
.api()
|
||||
|
||||
const success = await req.user.mfa_token.attempt_recovery(req.body.code)
|
||||
|
||||
if ( !success )
|
||||
return res.api({ success })
|
||||
|
||||
if ( req.trap.has_trap('mfa_challenge') )
|
||||
await req.trap.end()
|
||||
|
||||
let next_destination = req.session.auth.flow || this.configs.get('auth.default_login_route')
|
||||
delete req.session.auth.flow
|
||||
|
||||
req.session.mfa_remember = true
|
||||
|
||||
return res.api({
|
||||
success: true,
|
||||
next_destination,
|
||||
remaining_codes: req.user.mfa_token.recovery_codes.filter(x => !x.used).length,
|
||||
})
|
||||
}
|
||||
|
||||
async validate_email(req, res, next) {
|
||||
let is_valid = !!req.body.email
|
||||
|
||||
@@ -562,6 +597,37 @@ class AuthController extends Controller {
|
||||
})
|
||||
}
|
||||
|
||||
async get_mfa_recovery(req, res, next) {
|
||||
if ( !req.user.mfa_enabled )
|
||||
return res.status(400)
|
||||
.message('Your user does not have MFA enabled.')
|
||||
.api()
|
||||
|
||||
const token = req.user.mfa_token
|
||||
if ( !Array.isArray(token.recovery_codes) || token.recovery_codes.length < 1 )
|
||||
return res.api({ has_recovery: false })
|
||||
|
||||
return res.api({
|
||||
has_recovery: true,
|
||||
generated: token.recovery_codes[0].generated,
|
||||
remaining_codes: token.recovery_codes.filter(x => !x.used).length,
|
||||
})
|
||||
}
|
||||
|
||||
async generate_mfa_recovery(req, res, next) {
|
||||
if ( !req.user.mfa_enabled )
|
||||
return res.status(400)
|
||||
.message('Your user does not have MFA enabled.')
|
||||
.api()
|
||||
|
||||
const token = req.user.mfa_token
|
||||
const codes = await token.generate_recovery()
|
||||
await req.user.save()
|
||||
return res.api({
|
||||
codes,
|
||||
})
|
||||
}
|
||||
|
||||
async generate_mfa_key(req, res, next) {
|
||||
if ( req.user.mfa_enabled )
|
||||
return res.status(400)
|
||||
|
||||
@@ -54,6 +54,23 @@ class MFAController extends Controller {
|
||||
...this.Vue.session(req),
|
||||
})
|
||||
}
|
||||
|
||||
async get_recovery(req, res, next) {
|
||||
if (
|
||||
!req.user.mfa_enabled
|
||||
|| !Array.isArray(req.user.mfa_token.recovery_codes)
|
||||
|| req.user.mfa_token.recovery_codes.length < 1
|
||||
) return this.Vue.auth_message(res, {
|
||||
message: 'Unfortunately, it looks like your account does not have any MFA recovery codes generated.',
|
||||
next_destination: '/auth/mfa/challenge',
|
||||
button_text: 'Go Back',
|
||||
})
|
||||
|
||||
return res.page('auth:mfa:recovery', {
|
||||
...this.Vue.data(),
|
||||
...this.Vue.session(req),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = exports = MFAController
|
||||
|
||||
Reference in New Issue
Block a user