2019-06-13 06:16:55 +10:00
|
|
|
import RecoveryCodes from './mfa_backup_codes.vue'
|
|
|
|
import TOTP from './mfa_totp.vue'
|
|
|
|
import Confirm from './confirm.vue'
|
|
|
|
import VueQrcode from '@chenfengyuan/vue-qrcode'
|
|
|
|
import { mapState } from 'vuex'
|
|
|
|
|
|
|
|
const Mfa = {
|
|
|
|
data: () => ({
|
|
|
|
settings: { // current settings of MFA
|
2019-06-17 03:33:40 +10:00
|
|
|
available: false,
|
2019-06-13 06:16:55 +10:00
|
|
|
enabled: false,
|
|
|
|
totp: false
|
|
|
|
},
|
|
|
|
setupState: { // setup mfa
|
|
|
|
state: '', // state of setup. '' -> 'getBackupCodes' -> 'setupOTP' -> 'complete'
|
|
|
|
setupOTPState: '' // state of setup otp. '' -> 'prepare' -> 'confirm' -> 'complete'
|
|
|
|
},
|
|
|
|
backupCodes: {
|
|
|
|
getNewCodes: false,
|
|
|
|
inProgress: false, // progress of fetch codes
|
|
|
|
codes: []
|
|
|
|
},
|
|
|
|
otpSettings: { // pre-setup setting of OTP. secret key, qrcode url.
|
|
|
|
provisioning_uri: '',
|
|
|
|
key: ''
|
|
|
|
},
|
|
|
|
currentPassword: null,
|
|
|
|
otpConfirmToken: null,
|
|
|
|
error: null,
|
|
|
|
readyInit: false
|
|
|
|
}),
|
|
|
|
components: {
|
|
|
|
'recovery-codes': RecoveryCodes,
|
|
|
|
'totp-item': TOTP,
|
|
|
|
'qrcode': VueQrcode,
|
|
|
|
'confirm': Confirm
|
|
|
|
},
|
|
|
|
computed: {
|
|
|
|
canSetupOTP () {
|
|
|
|
return (
|
|
|
|
(this.setupInProgress && this.backupCodesPrepared) ||
|
|
|
|
this.settings.enabled
|
|
|
|
) && !this.settings.totp && !this.setupOTPInProgress
|
|
|
|
},
|
|
|
|
setupInProgress () {
|
|
|
|
return this.setupState.state !== '' && this.setupState.state !== 'complete'
|
|
|
|
},
|
|
|
|
setupOTPInProgress () {
|
|
|
|
return this.setupState.state === 'setupOTP' && !this.completedOTP
|
|
|
|
},
|
|
|
|
prepareOTP () {
|
|
|
|
return this.setupState.setupOTPState === 'prepare'
|
|
|
|
},
|
|
|
|
confirmOTP () {
|
|
|
|
return this.setupState.setupOTPState === 'confirm'
|
|
|
|
},
|
|
|
|
completedOTP () {
|
|
|
|
return this.setupState.setupOTPState === 'completed'
|
|
|
|
},
|
|
|
|
backupCodesPrepared () {
|
|
|
|
return !this.backupCodes.inProgress && this.backupCodes.codes.length > 0
|
|
|
|
},
|
|
|
|
confirmNewBackupCodes () {
|
|
|
|
return this.backupCodes.getNewCodes
|
|
|
|
},
|
|
|
|
...mapState({
|
|
|
|
backendInteractor: (state) => state.api.backendInteractor
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
methods: {
|
|
|
|
activateOTP () {
|
|
|
|
if (!this.settings.enabled) {
|
|
|
|
this.setupState.state = 'getBackupcodes'
|
|
|
|
this.fetchBackupCodes()
|
|
|
|
}
|
|
|
|
},
|
|
|
|
fetchBackupCodes () {
|
|
|
|
this.backupCodes.inProgress = true
|
|
|
|
this.backupCodes.codes = []
|
|
|
|
|
|
|
|
return this.backendInteractor.generateMfaBackupCodes()
|
|
|
|
.then((res) => {
|
|
|
|
this.backupCodes.codes = res.codes
|
|
|
|
this.backupCodes.inProgress = false
|
|
|
|
})
|
|
|
|
},
|
|
|
|
getBackupCodes () { // get a new backup codes
|
|
|
|
this.backupCodes.getNewCodes = true
|
|
|
|
},
|
|
|
|
confirmBackupCodes () { // confirm getting new backup codes
|
|
|
|
this.fetchBackupCodes().then((res) => {
|
|
|
|
this.backupCodes.getNewCodes = false
|
|
|
|
})
|
|
|
|
},
|
|
|
|
cancelBackupCodes () { // cancel confirm form of new backup codes
|
|
|
|
this.backupCodes.getNewCodes = false
|
|
|
|
},
|
|
|
|
|
|
|
|
// Setup OTP
|
|
|
|
setupOTP () { // prepare setup OTP
|
|
|
|
this.setupState.state = 'setupOTP'
|
|
|
|
this.setupState.setupOTPState = 'prepare'
|
|
|
|
this.backendInteractor.mfaSetupOTP()
|
|
|
|
.then((res) => {
|
|
|
|
this.otpSettings = res
|
|
|
|
this.setupState.setupOTPState = 'confirm'
|
|
|
|
})
|
|
|
|
},
|
|
|
|
doConfirmOTP () { // handler confirm enable OTP
|
|
|
|
this.error = null
|
|
|
|
this.backendInteractor.mfaConfirmOTP({
|
|
|
|
token: this.otpConfirmToken,
|
|
|
|
password: this.currentPassword
|
|
|
|
})
|
|
|
|
.then((res) => {
|
|
|
|
if (res.error) {
|
|
|
|
this.error = res.error
|
|
|
|
return
|
|
|
|
}
|
|
|
|
this.completeSetup()
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
completeSetup () {
|
|
|
|
this.setupState.setupOTPState = 'complete'
|
|
|
|
this.setupState.state = 'complete'
|
|
|
|
this.currentPassword = null
|
|
|
|
this.error = null
|
|
|
|
this.fetchSettings()
|
|
|
|
},
|
|
|
|
cancelSetup () { // cancel setup
|
|
|
|
this.setupState.setupOTPState = ''
|
|
|
|
this.setupState.state = ''
|
|
|
|
this.currentPassword = null
|
|
|
|
this.error = null
|
|
|
|
},
|
|
|
|
// end Setup OTP
|
|
|
|
|
|
|
|
// fetch settings from server
|
|
|
|
async fetchSettings () {
|
|
|
|
let result = await this.backendInteractor.fetchSettingsMFA()
|
2019-06-17 03:33:40 +10:00
|
|
|
if (result.error) return
|
2019-06-13 06:16:55 +10:00
|
|
|
this.settings = result.settings
|
2019-06-17 03:33:40 +10:00
|
|
|
this.settings.available = true
|
2019-06-13 06:16:55 +10:00
|
|
|
return result
|
|
|
|
}
|
|
|
|
},
|
|
|
|
mounted () {
|
|
|
|
this.fetchSettings().then(() => {
|
|
|
|
this.readyInit = true
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
export default Mfa
|