You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ha...@apache.org on 2022/11/27 17:18:39 UTC

[cloudstack] branch 2FA updated (9e1aea878b7 -> 20a971d5afe)

This is an automated email from the ASF dual-hosted git repository.

harikrishna pushed a change to branch 2FA
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


    from 9e1aea878b7 Added Disable 2FA on form closure
     new a378431d444 Added setup 2FA at login page
     new 9018e884155 Fixed 2FA at login page
     new 20a971d5afe icons for 2FA providers

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 server/src/main/java/com/cloud/api/ApiServlet.java |  6 +-
 ui/public/locales/en.json                          |  2 +-
 ui/src/config/router.js                            |  9 +++
 ui/src/core/lazy_lib/icons_use.js                  |  2 +
 ui/src/permission.js                               |  2 +-
 ui/src/views/auth/Login.vue                        |  4 +-
 ui/src/views/dashboard/Dashboard.vue               |  4 +-
 .../SetupTwoFaAtLogin.vue}                         | 40 +++++++++--
 ui/src/views/dashboard/VerifyTwoFa.vue             | 83 ++++++++++++----------
 ui/src/views/iam/RegisterTwoFactorAuth.vue         | 25 ++++++-
 10 files changed, 129 insertions(+), 48 deletions(-)
 copy ui/src/views/{iam/RegisterTwoFactorAuth.vue => dashboard/SetupTwoFaAtLogin.vue} (87%)


[cloudstack] 03/03: icons for 2FA providers

Posted by ha...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

harikrishna pushed a commit to branch 2FA
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit 20a971d5afe2e33495444773dda1196f8c567340
Author: Harikrishna Patnala <ha...@gmail.com>
AuthorDate: Sun Nov 27 08:26:10 2022 +0530

    icons for 2FA providers
---
 ui/public/locales/en.json                    |  2 +-
 ui/src/core/lazy_lib/icons_use.js            |  2 ++
 ui/src/views/dashboard/SetupTwoFaAtLogin.vue |  3 +--
 ui/src/views/iam/RegisterTwoFactorAuth.vue   | 24 +++++++++++++++++++++++-
 4 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json
index 31f9783dded..cb3508e47ae 100644
--- a/ui/public/locales/en.json
+++ b/ui/public/locales/en.json
@@ -2591,7 +2591,7 @@
 "message.traffic.type.to.basic.zone": "traffic type to basic zone",
 "message.two.fa.auth": "<br>1. Open the authenticator application on your device <br>2. Enter the authentication code of the user to verify",
 "message.two.fa.register.account": "1. Open the authenticator application on your device <br>2. Scan the below QR code to add the user <br>3. If you cannot scan the QR code, enter the setup key manually <br>4. Verification of the 2FA code is mandatory to complete the 2FA setup",
-"message.two.fa.staticpin": "1. Use the generated static pin as 2FA code for two factor authentication<br>2. Verification of the 2FA code is mandatory to complete the 2FA setup",
+"message.two.fa.staticpin": "1. Use the generated static pin as 2FA code for two factor authentication<br>2. Save this static pin/2FA code and do not share<br>3. Verification of the 2FA code is mandatory to complete the 2FA setup",
 "message.two.fa.view.setup.key": "Click here to view the setup key",
 "message.two.fa.view.static.pin": "Click here to view the static pin",
 "message.update.ipaddress.processing": "Updating IP Address...",
diff --git a/ui/src/core/lazy_lib/icons_use.js b/ui/src/core/lazy_lib/icons_use.js
index 39627ed76ef..6fce9dd2cb8 100644
--- a/ui/src/core/lazy_lib/icons_use.js
+++ b/ui/src/core/lazy_lib/icons_use.js
@@ -90,6 +90,7 @@ import {
   GithubOutlined,
   GlobalOutlined,
   GoldOutlined,
+  GoogleOutlined,
   HddOutlined,
   HomeOutlined,
   IdcardOutlined,
@@ -238,6 +239,7 @@ export default {
     app.component('GithubOutlined', GithubOutlined)
     app.component('GlobalOutlined', GlobalOutlined)
     app.component('GoldOutlined', GoldOutlined)
+    app.component('GoogleOutlined', GoogleOutlined)
     app.component('HddOutlined', HddOutlined)
     app.component('HomeOutlined', HomeOutlined)
     app.component('IdcardOutlined', IdcardOutlined)
diff --git a/ui/src/views/dashboard/SetupTwoFaAtLogin.vue b/ui/src/views/dashboard/SetupTwoFaAtLogin.vue
index 0c1d8202974..a3f7312530a 100644
--- a/ui/src/views/dashboard/SetupTwoFaAtLogin.vue
+++ b/ui/src/views/dashboard/SetupTwoFaAtLogin.vue
@@ -46,8 +46,7 @@
           @change="val => { handleSelectChange(val) }">
           <a-select-option
             v-for="(opt) in providers"
-            :key="opt.name"
-            :disabled="opt.enabled === false">
+            :key="opt.name">
               {{ opt.name }}
           </a-select-option>
         </a-select>
diff --git a/ui/src/views/iam/RegisterTwoFactorAuth.vue b/ui/src/views/iam/RegisterTwoFactorAuth.vue
index 7404a58613a..c8f9641ca05 100644
--- a/ui/src/views/iam/RegisterTwoFactorAuth.vue
+++ b/ui/src/views/iam/RegisterTwoFactorAuth.vue
@@ -34,12 +34,34 @@
           <a-select-option
             v-for="(opt) in providers"
             :key="opt.name"
-            :disabled="opt.enabled === false">
+            :value="opt.name">
+            <div>
+              <span v-if="opt.name === 'google'">
+                <google-outlined />
+              </span>
+              <span v-if="opt.name === 'staticpin'">
+                <google-outlined />
+              </span>
               {{ opt.name }}
+            </div>
           </a-select-option>
         </a-select>
         <div :span="24" v-if="selectedProvider">
           <a-button ref="submit" type="primary" @click="setup2FAProvider">{{ $t('label.setup') }}</a-button>
+          <tooltip-button
+            tooltipPlacement="top"
+            :tooltip="$t('label.accept.project.invitation')"
+            icon="check-outlined"
+            size="small"
+            @onClick="setup2FAProvider()"/>
+          <tooltip-button
+            tooltipPlacement="top"
+            :tooltip="$t('label.decline.invitation')"
+            type="primary"
+            :danger="true"
+            icon="close-outlined"
+            size="small"
+            @onClick="setup2FAProvider()"/>
         </div>
       </div>
       <div v-if="twoFAenabled">


[cloudstack] 01/03: Added setup 2FA at login page

Posted by ha...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

harikrishna pushed a commit to branch 2FA
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit a378431d44487e07eda6dd5ab66c3d0192cc7b94
Author: Harikrishna Patnala <ha...@gmail.com>
AuthorDate: Fri Nov 25 14:32:13 2022 +0530

    Added setup 2FA at login page
---
 server/src/main/java/com/cloud/api/ApiServlet.java |  6 +-
 ui/src/config/router.js                            |  9 +++
 ui/src/permission.js                               |  2 +-
 ui/src/views/auth/Login.vue                        |  2 +
 ui/src/views/dashboard/Dashboard.vue               |  4 +-
 ui/src/views/dashboard/VerifyTwoFa.vue             | 83 ++++++++++++----------
 ui/src/views/iam/RegisterTwoFactorAuth.vue         |  1 +
 7 files changed, 66 insertions(+), 41 deletions(-)

diff --git a/server/src/main/java/com/cloud/api/ApiServlet.java b/server/src/main/java/com/cloud/api/ApiServlet.java
index ef7407062a4..f7b8a4f66ba 100644
--- a/server/src/main/java/com/cloud/api/ApiServlet.java
+++ b/server/src/main/java/com/cloud/api/ApiServlet.java
@@ -35,6 +35,8 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
+import com.cloud.api.auth.ListUserTwoFactorAuthenticatorProvidersCmd;
+import com.cloud.api.auth.SetupUserTwoFactorAuthenticationCmd;
 import com.cloud.api.auth.ValidateUserTwoFactorAuthenticationCodeCmd;
 import com.cloud.user.UserAccount;
 import org.apache.cloudstack.api.ApiConstants;
@@ -300,7 +302,9 @@ public class ApiServlet extends HttpServlet {
                 s_logger.trace(String.format("new session: %s", session));
             }
 
-            if (!isNew && !command.equalsIgnoreCase(ApiConstants.LIST_IDPS)) {
+            if (!isNew && !command.equalsIgnoreCase(ApiConstants.LIST_IDPS)
+                    && !command.equalsIgnoreCase(ListUserTwoFactorAuthenticatorProvidersCmd.APINAME)
+                    && !command.equalsIgnoreCase(SetupUserTwoFactorAuthenticationCmd.APINAME)) {
                 s_logger.debug("Checking if two factor authentication is enabled, if enabled it will be verified");
                 userId = (Long)session.getAttribute("userid");
                 UserAccount userAccount = accountMgr.getUserAccountById(userId);
diff --git a/ui/src/config/router.js b/ui/src/config/router.js
index a1d5be7522d..e1c83255530 100644
--- a/ui/src/config/router.js
+++ b/ui/src/config/router.js
@@ -316,6 +316,15 @@ export const constantRouterMap = [
     },
     component: () => import('@/views/dashboard/VerifyTwoFa')
   },
+  {
+    path: '/setup2FA',
+    name: 'SetupTwoFaAtLogin',
+    meta: {
+      title: 'label.two.factor.authentication',
+      hidden: true
+    },
+    component: () => import('@/views/dashboard/SetupTwoFaAtLogin')
+  },
   {
     path: '/403',
     component: () => import(/* webpackChunkName: "forbidden" */ '@/views/exception/403')
diff --git a/ui/src/permission.js b/ui/src/permission.js
index 8dbed2e950e..b26242a9159 100644
--- a/ui/src/permission.js
+++ b/ui/src/permission.js
@@ -59,7 +59,7 @@ router.beforeEach((to, from, next) => {
     if (to.path === '/user/login') {
       next({ path: '/dashboard' })
       NProgress.done()
-    } else if (to.path === '/verify2FA') {
+    } else if (to.path === '/verify2FA' || to.path === '/setup2FA') {
       if (store.getters.twoFaEnabled && !store.getters.loginFlag) {
         console.log('Do Two-factor authentication')
         next()
diff --git a/ui/src/views/auth/Login.vue b/ui/src/views/auth/Login.vue
index 0a64fbe3925..e4c52eaded9 100644
--- a/ui/src/views/auth/Login.vue
+++ b/ui/src/views/auth/Login.vue
@@ -300,6 +300,8 @@ export default {
       this.$store.commit('SET_COUNT_NOTIFY', 0)
       if (store.getters.twoFaEnabled === true && store.getters.twoFaProvider !== '') {
         this.$router.push({ path: '/verify2FA' }).catch(() => {})
+      } else if (store.getters.twoFaEnabled === true && store.getters.twoFaProvider === '') {
+        this.$router.push({ path: '/setup2FA' }).catch(() => {})
       } else {
         this.$store.commit('SET_LOGIN_FLAG', true)
         this.$router.push({ path: '/dashboard' }).catch(() => {})
diff --git a/ui/src/views/dashboard/Dashboard.vue b/ui/src/views/dashboard/Dashboard.vue
index e5bab748fb6..ea8e385decb 100644
--- a/ui/src/views/dashboard/Dashboard.vue
+++ b/ui/src/views/dashboard/Dashboard.vue
@@ -36,6 +36,7 @@ import CapacityDashboard from './CapacityDashboard'
 import UsageDashboard from './UsageDashboard'
 import OnboardingDashboard from './OnboardingDashboard'
 import VerifyTwoFa from './VerifyTwoFa'
+import SetupTwoFaAtLogin from './SetupTwoFaAtLogin'
 
 export default {
   name: 'Dashboard',
@@ -43,7 +44,8 @@ export default {
     CapacityDashboard,
     UsageDashboard,
     OnboardingDashboard,
-    VerifyTwoFa
+    VerifyTwoFa,
+    SetupTwoFaAtLogin
   },
   provide: function () {
     return {
diff --git a/ui/src/views/dashboard/VerifyTwoFa.vue b/ui/src/views/dashboard/VerifyTwoFa.vue
index acbd87170a5..9dca8c715da 100644
--- a/ui/src/views/dashboard/VerifyTwoFa.vue
+++ b/ui/src/views/dashboard/VerifyTwoFa.vue
@@ -16,44 +16,42 @@
 // under the License.
 
 <template>
-  <a-form>
-    <img
-      v-if="$config.banner"
-      :style="{
-        width: $config.theme['@banner-width'],
-        height: $config.theme['@banner-height']
-      }"
-      :src="$config.banner"
-      class="user-layout-logo"
-      alt="logo">
-    <h1 style="text-align: center; font-size: 24px; color: gray"> {{ $t('label.two.factor.authentication') }} </h1>
-    <br />
-    <br />
-    <a-form
-      :ref="formRef"
-      :model="form"
-      :rules="rules"
-      @finish="handleSubmit"
-      layout="vertical">
-      <a-form-item name="code" ref="code">
-        <a-input
-          class="center-align"
-          style="width: 400px"
-          v-model:value="form.code"
-          placeholder="xxxxxxx" />
-      </a-form-item>
-      <div :span="24" class="center-align top-padding">
-          <a-button
-            :loading="loading"
-            ref="submit"
-            type="primary"
+  <div class="center">
+    <a-form>
+      <img
+        v-if="$config.banner"
+        :src="$config.banner"
+        class="user-layout-logo"
+        alt="logo">
+      <h1 style="text-align: center; font-size: 24px; color: gray"> {{ $t('label.two.factor.authentication') }} </h1>
+      <br />
+      <br />
+      <a-form
+        :ref="formRef"
+        :model="form"
+        :rules="rules"
+        @finish="handleSubmit"
+        layout="vertical">
+        <a-form-item name="code" ref="code">
+          <a-input
             class="center-align"
-            @click="handleSubmit">{{ $t('label.verify') }}
-          </a-button>
-        </div>
-      <p style="text-align: center" v-html="$t('message.two.fa.auth')"></p>
+            style="width: 400px"
+            v-model:value="form.code"
+            placeholder="xxxxxxx" />
+        </a-form-item>
+        <div :span="24" class="center-align top-padding">
+            <a-button
+              :loading="loading"
+              ref="submit"
+              type="primary"
+              class="center-align"
+              @click="handleSubmit">{{ $t('label.verify') }}
+            </a-button>
+          </div>
+        <p style="text-align: center" v-html="$t('message.two.fa.auth')"></p>
+      </a-form>
     </a-form>
-  </a-form>
+  </div>
 </template>
 <script>
 
@@ -61,7 +59,7 @@ import { api } from '@/api'
 import { ref, reactive, toRaw } from 'vue'
 
 export default {
-  name: 'TwoFa',
+  name: 'VerifyTwoFa',
   data () {
     return {
       twoFAresponse: false
@@ -95,7 +93,6 @@ export default {
             })
             this.$emit('refresh-data')
           }
-          console.log(response)
         }).catch(error => {
           this.$notification.error({
             message: this.$t('message.request.failed'),
@@ -108,6 +105,16 @@ export default {
 }
 </script>
 <style lang="less" scoped>
+  .center {
+    position: fixed;
+    top: 42.5%;
+    left: 50%;
+    -webkit-transform: translate(-50%, -50%);
+
+    background-color: #D3D3D3;
+    padding: 70px 50px 70px 50px;
+    z-index: 100;
+  }
   .center-align {
     display: block;
     margin-left: auto;
diff --git a/ui/src/views/iam/RegisterTwoFactorAuth.vue b/ui/src/views/iam/RegisterTwoFactorAuth.vue
index 122c484eec7..7404a58613a 100644
--- a/ui/src/views/iam/RegisterTwoFactorAuth.vue
+++ b/ui/src/views/iam/RegisterTwoFactorAuth.vue
@@ -23,6 +23,7 @@
       layout="vertical">
       <div class="form-layout form-align" v-ctrl-enter="submitPin">
          <a-select
+          :disabled="twoFAenabled === true"
           v-model:value="selectedProvider"
           optionFilterProp="label"
           :filterOption="(input, option) => {


[cloudstack] 02/03: Fixed 2FA at login page

Posted by ha...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

harikrishna pushed a commit to branch 2FA
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit 9018e8841556f4d6ca75a51d256d3262ebce03bf
Author: Harikrishna Patnala <ha...@gmail.com>
AuthorDate: Fri Nov 25 16:03:05 2022 +0530

    Fixed 2FA at login page
---
 ui/src/views/auth/Login.vue                  |   4 +-
 ui/src/views/dashboard/SetupTwoFaAtLogin.vue | 248 +++++++++++++++++++++++++++
 2 files changed, 250 insertions(+), 2 deletions(-)

diff --git a/ui/src/views/auth/Login.vue b/ui/src/views/auth/Login.vue
index e4c52eaded9..34f5a7040d5 100644
--- a/ui/src/views/auth/Login.vue
+++ b/ui/src/views/auth/Login.vue
@@ -298,9 +298,9 @@ export default {
     loginSuccess (res) {
       this.$notification.destroy()
       this.$store.commit('SET_COUNT_NOTIFY', 0)
-      if (store.getters.twoFaEnabled === true && store.getters.twoFaProvider !== '') {
+      if (store.getters.twoFaEnabled === true && store.getters.twoFaProvider !== '' && store.getters.twoFaProvider !== undefined) {
         this.$router.push({ path: '/verify2FA' }).catch(() => {})
-      } else if (store.getters.twoFaEnabled === true && store.getters.twoFaProvider === '') {
+      } else if (store.getters.twoFaEnabled === true && (store.getters.twoFaProvider === '' || store.getters.twoFaProvider === undefined)) {
         this.$router.push({ path: '/setup2FA' }).catch(() => {})
       } else {
         this.$store.commit('SET_LOGIN_FLAG', true)
diff --git a/ui/src/views/dashboard/SetupTwoFaAtLogin.vue b/ui/src/views/dashboard/SetupTwoFaAtLogin.vue
new file mode 100644
index 00000000000..0c1d8202974
--- /dev/null
+++ b/ui/src/views/dashboard/SetupTwoFaAtLogin.vue
@@ -0,0 +1,248 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+<template>
+  <div class="center">
+    <a-form>
+      <img
+        v-if="$config.banner"
+        :style="{
+          width: $config.theme['@banner-width'],
+          height: $config.theme['@banner-height']
+        }"
+        :src="$config.banner"
+        class="user-layout-logo"
+        alt="logo">
+      <h1 style="text-align: center; font-size: 24px; color: gray"> {{ $t('label.two.factor.authentication') }} </h1>
+      <br />
+      <br />
+    </a-form>
+    <h3> {{ $t('label.select.2fa.provider') }} </h3>
+    <a-form
+      :rules="rules"
+      layout="vertical">
+      <div class="form-layout form-align" v-ctrl-enter="submitPin">
+         <a-select
+          :disabled="twoFAenabled === true"
+          v-model:value="selectedProvider"
+          optionFilterProp="label"
+          :filterOption="(input, option) => {
+            return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+          }"
+          style="width: 100%"
+          @change="val => { handleSelectChange(val) }">
+          <a-select-option
+            v-for="(opt) in providers"
+            :key="opt.name"
+            :disabled="opt.enabled === false">
+              {{ opt.name }}
+          </a-select-option>
+        </a-select>
+        <div :span="24" v-if="selectedProvider">
+          <a-button ref="submit" type="primary" @click="setup2FAProvider">{{ $t('label.setup') }}</a-button>
+        </div>
+      </div>
+      <div v-if="twoFAenabled">
+        <div v-if="selectedProvider !== 'staticpin'">
+          <br />
+          <p v-html="$t('message.two.fa.register.account')"></p>
+          <vue-qrious
+            class="center-align"
+            :value="googleUrl"
+            @change="onDataUrlChange"
+          />
+          <div style="text-align: center"> <a @click="showConfiguredPin"> {{ $t('message.two.fa.view.setup.key') }}</a></div>
+        </div>
+        <div v-if="selectedProvider === 'staticpin'">
+          <br>
+          <p v-html="$t('message.two.fa.staticpin')"></p>
+          <br>
+          <div> <a @click="showConfiguredPin"> {{ $t('message.two.fa.view.static.pin') }}</a></div>
+        </div>
+        <div v-if="selectedProvider">
+          <br />
+          <h3> {{ $t('label.enter.code') }} </h3>
+          <a-form @finish="submitPin" v-ctrl-enter="submitPin" class="container">
+            <a-input v-model:value="code" />
+            <div :span="24">
+              <a-button ref="submit" type="primary" @click="submitPin">{{ $t('label.verify') }}</a-button>
+            </div>
+          </a-form>
+        </div>
+
+        <a-modal
+          v-if="showPin"
+          :visible="showPin"
+          :title="$t(selectedProvider === 'staticpin'? 'label.two.factor.authentication.static.pin' : 'label.two.factor.authentication.secret.key')"
+          :closable="true"
+          :footer="null"
+          @cancel="onCloseModal"
+          centered
+          width="450px">
+          <div> {{ pin }} </div>
+        </a-modal>
+      </div>
+    </a-form>
+  </div>
+</template>
+<script>
+
+import { api } from '@/api'
+import VueQrious from 'vue-qrious'
+import eventBus from '@/config/eventBus'
+export default {
+  name: 'RegisterTwoFactorAuth',
+  props: {
+    resource: {
+      type: Object,
+      required: true
+    }
+  },
+  components: {
+    VueQrious
+  },
+  data () {
+    return {
+      googleUrl: '',
+      dataUrl: '',
+      pin: '',
+      code: '',
+      showPin: false,
+      twoFAenabled: false,
+      twoFAverified: false,
+      providers: [],
+      selectedProvider: null
+    }
+  },
+  mounted () {
+    this.list2FAProviders()
+  },
+  created () {
+    eventBus.on('action-closing', (args) => {
+      if (args.action.api === 'setupUserTwoFactorAuthentication' && this.twoFAenabled && !this.twoFAverified) {
+        this.disable2FAProvider()
+      }
+    })
+  },
+  methods: {
+    onDataUrlChange (dataUrl) {
+      this.dataUrl = dataUrl
+    },
+    handleSelectChange (val) {
+      this.selectedProvider = val
+    },
+    setup2FAProvider () {
+      if (!this.twoFAenabled) {
+        api('setupUserTwoFactorAuthentication', { provider: this.selectedProvider }).then(response => {
+          console.log(response)
+          this.pin = response.setupusertwofactorauthenticationresponse.setup2fa.secretcode
+          if (this.selectedProvider === 'google') {
+            this.username = response.setupusertwofactorauthenticationresponse.setup2fa.username
+            this.googleUrl = 'otpauth://totp/CloudStack:' + this.username + '?secret=' + this.pin + '&issuer=CloudStack'
+            this.showPin = false
+          }
+          if (this.selectedProvider === 'staticpin') {
+            this.showPin = true
+          }
+          this.twoFAenabled = true
+          this.twoFAverified = false
+        }).catch(error => {
+          this.$notification.error({
+            message: this.$t('message.request.failed'),
+            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
+          })
+        })
+      }
+    },
+    disable2FAProvider () {
+      api('setupUserTwoFactorAuthentication', { enable: false }).then(response => {
+        this.showPin = false
+        this.twoFAenabled = false
+        this.twoFAverified = false
+      }).catch(error => {
+        this.$notification.error({
+          message: this.$t('message.request.failed'),
+          description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
+        })
+      })
+    },
+    list2FAProviders () {
+      api('listUserTwoFactorAuthenticatorProviders', {}).then(response => {
+        this.providers = response.listusertwofactorauthenticatorprovidersresponse.providers || []
+      })
+    },
+    submitPin () {
+      api('validateUserTwoFactorAuthenticationCode', { '2facode': this.code }).then(response => {
+        this.$message.success({
+          content: `${this.$t('label.action.enable.two.factor.authentication')}`,
+          duration: 2
+        })
+        this.$notification.destroy()
+        this.$store.commit('SET_COUNT_NOTIFY', 0)
+        this.$store.commit('SET_LOGIN_FLAG', true)
+        this.$router.push({ path: '/dashboard' }).catch(() => {})
+
+        this.twoFAverified = true
+        this.$emit('refresh-data')
+      }).catch(error => {
+        this.$notification.error({
+          message: this.$t('message.request.failed'),
+          description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
+        })
+      })
+      this.closeAction()
+    },
+    closeAction () {
+      this.$emit('close-action')
+    },
+    showConfiguredPin () {
+      this.showPin = true
+    },
+    onCloseModal () {
+      this.showPin = false
+    }
+  }
+}
+</script>
+
+<style scoped>
+  .center {
+    position: fixed;
+    top: 42.5%;
+    left: 50%;
+    -webkit-transform: translate(-50%, -50%);
+
+    background-color: #D3D3D3;
+    padding: 70px 50px 70px 50px;
+    z-index: 100;
+  }
+  .center-align {
+    display: block;
+    margin-left: auto;
+    margin-right: auto;
+  }
+  .form-align {
+    display: flex;
+    flex-direction: row;
+  }
+  .top-padding {
+    padding-top: 35px;
+  }
+  .container {
+    display: flex;
+  }
+
+</style>