1
0
Fix not telling the user about invalid totp passcodes when logging in

Add disabling totp authentication

Add totp passcode when logging in

Add totp settings

Add general post method function

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/109
This commit is contained in:
konrad
2020-04-17 23:46:07 +00:00
parent a75670e4f0
commit 99c10d49be
7 changed files with 220 additions and 31 deletions

View File

@ -18,6 +18,12 @@
<input type="password" class="input" id="password" name="password" placeholder="e.g. ••••••••••••" ref="password" required/>
</div>
</div>
<div class="field" v-if="needsTotpPasscode">
<label class="label" for="totpPasscode">Two Factor Authentication Code</label>
<div class="control">
<input type="text" class="input" id="totpPasscode" placeholder="e.g. 123456" ref="totpPasscode" required v-focus/>
</div>
</div>
<div class="field is-grouped">
<div class="control">
@ -45,7 +51,8 @@
return {
errorMsg: '',
confirmedEmailSuccess: false,
loading: false
loading: false,
needsTotpPasscode: false,
}
},
beforeMount() {
@ -83,6 +90,10 @@
password: this.$refs.password.value,
}
if(this.needsTotpPasscode) {
credentials.totpPasscode = this.$refs.totpPasscode.value
}
auth.login(this, credentials, 'home')
}
}

View File

@ -1,5 +1,5 @@
<template>
<div class="loader-container" v-bind:class="{ 'is-loading': passwordUpdateService.loading}">
<div class="loader-container" :class="{ 'is-loading': passwordUpdateService.loading || emailUpdateService.loading || totpService.loading }">
<div class="card">
<header class="card-header">
<p class="card-header-title">
@ -75,6 +75,52 @@
</div>
</div>
</div>
<div class="card">
<header class="card-header">
<p class="card-header-title">
Two Factor Authentication
</p>
</header>
<div class="card-content">
<a class="button is-primary" v-if="!totpEnrolled && totp.secret === ''" @click="totpEnroll()" :class="{ 'is-loading': totpService.loading }">Enroll</a>
<div class="content" v-else-if="totp.secret !== '' && !totp.enabled">
<p>
To finish your setup, use this secret in your totp app (Google Authenticator or similar): <strong>{{ totp.secret }}</strong><br/>
After that, enter a code from your app below.
</p>
<p>
Alternatively you can scan this QR code:<br/>
<img :src="totpQR" alt=""/>
</p>
<div class="field">
<label class="label" for="totpConfirmPasscode">Passcode</label>
<div class="control">
<input class="input" type="text" id="totpConfirmPasscode" placeholder="A code generated by your totp application"
v-model="totpConfirmPasscode" @keyup.enter="totpConfirm()"/>
</div>
</div>
<a class="button is-primary" @click="totpConfirm()">Confirm</a>
</div>
<div class="content" v-else-if="totp.secret !== '' && totp.enabled">
<p>
You've sucessfully set up two factor authentication!
</p>
<p v-if="!totpDisableForm">
<a class="button is-danger" @click="totpDisableForm = true">Disable</a>
</p>
<div v-if="totpDisableForm">
<div class="field">
<label class="label" for="currentPassword">Please Enter Your Password</label>
<div class="control">
<input class="input" type="password" id="currentPassword" placeholder="Your current password"
v-model="totpDisablePassword" @keyup.enter="totpDisable" v-focus/>
</div>
</div>
<a class="button is-danger" @click="totpDisable()">Disable two factor authentication</a>
</div>
</div>
</div>
</div>
</div>
</template>
@ -83,6 +129,8 @@
import PasswordUpdateService from '../../services/passwordUpdateService'
import EmailUpdateService from '../../services/emailUpdate'
import EmailUpdateModel from '../../models/emailUpdate'
import TotpModel from '../../models/totp'
import TotpService from '../../services/totp'
export default {
name: 'Settings',
@ -94,14 +142,40 @@
emailUpdateService: EmailUpdateService,
emailUpdate: EmailUpdateModel,
totpService: TotpService,
totp: TotpModel,
totpQR: '',
totpEnrolled: false,
totpConfirmPasscode: '',
totpDisableForm: false,
totpDisablePassword: '',
}
},
created() {
this.passwordUpdate = new PasswordUpdateModel()
this.passwordUpdateService = new PasswordUpdateService()
this.passwordUpdate = new PasswordUpdateModel()
this.emailUpdate = new EmailUpdateModel()
this.emailUpdateService = new EmailUpdateService()
this.emailUpdate = new EmailUpdateModel()
this.totpService = new TotpService()
this.totp = new TotpModel()
this.totpService.get()
.then(r => {
this.$set(this, 'totp', r)
this.totpSetQrCode()
})
.catch(e => {
// Error code 1016 means totp is not enabled, we don't need an error in that case.
if (e.response && e.response.data && e.response.data.code && e.response.data.code === 1016) {
this.totpEnrolled = false
return
}
this.error(e, this)
})
},
methods: {
updatePassword() {
@ -123,6 +197,39 @@
})
.catch(e => this.error(e, this))
},
totpSetQrCode() {
this.totpService.qrcode()
.then(qr => {
const urlCreator = window.URL || window.webkitURL
this.totpQR = urlCreator.createObjectURL(qr)
})
},
totpEnroll() {
this.totpService.enroll()
.then(r => {
this.totpEnrolled = true
this.$set(this, 'totp', r)
this.totpSetQrCode()
})
.catch(e => this.error(e, this))
},
totpConfirm() {
this.totpService.enable({passcode: this.totpConfirmPasscode})
.then(() => {
this.$set(this.totp, 'enabled', true)
this.success({message: 'You\'ve successfully confirmed your totp setup and can use it from now on!'}, this)
})
.catch(e => this.error(e, this))
},
totpDisable() {
this.totpService.disable({password: this.totpDisablePassword})
.then(() => {
this.totpEnrolled = false
this.$set(this, 'totp', new TotpModel())
this.success({message: 'Two factor authentication was sucessfully disabled.'}, this)
})
.catch(e => this.error(e, this))
},
},
}
</script>