From 240b7e3ac70c9d1ac91a69abfd3f943045a8cf31 Mon Sep 17 00:00:00 2001 From: Jonathan Cobb Date: Thu, 19 Dec 2019 19:32:47 -0500 Subject: [PATCH] start adding MFA login support --- src/_helpers/router.js | 4 ++- src/_store/account.module.js | 26 ++++++++++---- src/_store/users.module.js | 29 +++++++++++++--- src/account/profile/PolicyPage.vue | 56 ++++++++++++++++++------------ src/auth/MultifactorAuthPage.vue | 19 ++++++++++ 5 files changed, 100 insertions(+), 34 deletions(-) create mode 100644 src/auth/MultifactorAuthPage.vue diff --git a/src/_helpers/router.js b/src/_helpers/router.js index 54ffff2..748b9f4 100644 --- a/src/_helpers/router.js +++ b/src/_helpers/router.js @@ -4,6 +4,7 @@ import Router from 'vue-router'; import HomePage from '../account/HomePage' import RegisterPage from '../auth/RegisterPage' import LoginPage from '../auth/LoginPage' +import MultifactorAuthPage from '../auth/MultifactorAuthPage' import ProfilePage from '../account/profile/ProfilePage' import ActionPage from '../account/profile/ActionPage' import PolicyPage from '../account/profile/PolicyPage' @@ -64,6 +65,7 @@ export const router = new Router({ }, { path: '/action', component: ActionPage }, { path: '/register', component: RegisterPage }, + { path: '/auth', component: MultifactorAuthPage }, { path: '/login', component: LoginPage }, { path: '/logout', component: LoginPage }, { path: '/admin/accounts', component: AccountsPage }, @@ -75,7 +77,7 @@ export const router = new Router({ }); router.beforeEach((to, from, next) => { - const publicPages = ['/login', '/logout', '/register']; + const publicPages = ['/login', '/logout', '/register', '/auth']; const authRequired = !publicPages.includes(to.path); const user = currentUser(); diff --git a/src/_store/account.module.js b/src/_store/account.module.js index ed51b1f..b5564f4 100644 --- a/src/_store/account.module.js +++ b/src/_store/account.module.js @@ -16,12 +16,18 @@ const actions = { .then( user => { commit('loginSuccess', user); - const landing = getLandingPage(); - if (landing === null) { - router.push('/'); - } else { - resetLandingPage(); - router.push(landing.fullPath); + if (user.token) { + const landing = getLandingPage(); + if (landing === null) { + router.push('/'); + } else { + resetLandingPage(); + router.push(landing.fullPath); + } + } else if (user.multifactorAuth) { + // todo: create a page that shows what auths are required and allows the user + // to manually enter each code + // periodically poll for status, if all auths have been provided, log the user in } }, error => { @@ -103,7 +109,13 @@ const mutations = { state.user = user; }, loginSuccess(state, user) { - state.status = { loggedIn: true }; + if (user.token) { + state.status = { loggedIn: true }; + } else if (user.multifactorAuth) { + state.status = { multifactorAuth: true }; + } else { + state.status = {}; + } state.user = user; }, loginFailure(state) { diff --git a/src/_store/users.module.js b/src/_store/users.module.js index f71f3d4..491a1b5 100644 --- a/src/_store/users.module.js +++ b/src/_store/users.module.js @@ -10,13 +10,33 @@ const state = { authenticator: {} }; +export const CONTACT_TYPE_AUTHENTICATOR = 'authenticator'; +export function isAuthenticator (val) { + return val === CONTACT_TYPE_AUTHENTICATOR || (val != null && typeof val.type !== 'undefined' && val.type === CONTACT_TYPE_AUTHENTICATOR); +} +export function isNotAuthenticator (val) { return !isAuthenticator(val); } + +const LOCALSTORAGE_AUTHENTICATOR = 'authenticator'; + function setAuthenticator(policy) { + const storedAuthJson = localStorage.getItem(LOCALSTORAGE_AUTHENTICATOR); + const storedAuth = storedAuthJson !== null ? JSON.parse(storedAuthJson) : null; if (policy && policy.accountContacts) { const contacts = policy.accountContacts; for (let i=0; i {{contact.nick}} {{messages['field_label_policy_contact_type_'+contact.type]}} - {{contact.info}} + {{contact.info}} {{messages.message_true}} -
-
-
+ +
+ + {{messages.message_verify_authenticator_masked}} +
+
+
{{messages.message_verify_authenticator_preamble}}

@@ -126,10 +130,10 @@
{{ errors.first('token') }}
- +
- + @@ -176,7 +180,7 @@ {{messages.message_false}} - + {{messages.field_label_policy_contact_value_not_applicable_name}} @@ -189,7 +193,7 @@ {{messages.message_false}} - + {{messages.field_label_policy_contact_value_not_applicable_name}} @@ -202,7 +206,7 @@ {{messages.message_false}} - + {{messages.field_label_policy_contact_value_not_applicable_name}} @@ -215,7 +219,7 @@ {{messages.message_false}} - + {{messages.field_label_policy_contact_value_not_applicable_name}} @@ -228,7 +232,7 @@ {{messages.message_false}} - + {{messages.field_label_policy_contact_value_not_applicable_name}} @@ -260,7 +264,7 @@
{{ errors.first('contactType') }}
-
+
@@ -283,23 +287,23 @@
-
+
-
+
-
+
-
+
-
+
@@ -323,6 +327,12 @@ \ No newline at end of file