From c836157edb869e80b15f51bb8f48725e3b898b9a Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 22 Sep 2023 14:12:33 +0900 Subject: enhance: 二要素認証設定時のセキュリティを強化 (#11863) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * enhance: 二要素認証設定時のセキュリティを強化 パスワード入力が必要な操作を行う際、二要素認証が有効であれば確認コードの入力も必要にする * Update CoreModule.ts * Update 2fa.ts * wip * wip * Update 2fa.ts * tweak --- packages/frontend/src/pages/settings/2fa.vue | 65 ++++++++++------------- packages/frontend/src/pages/settings/email.vue | 20 ++++--- packages/frontend/src/pages/settings/other.vue | 10 ++-- packages/frontend/src/pages/settings/security.vue | 29 +++++----- 4 files changed, 53 insertions(+), 71 deletions(-) (limited to 'packages/frontend/src/pages/settings') diff --git a/packages/frontend/src/pages/settings/2fa.vue b/packages/frontend/src/pages/settings/2fa.vue index 37455ac2d0..8a89a3a86d 100644 --- a/packages/frontend/src/pages/settings/2fa.vue +++ b/packages/frontend/src/pages/settings/2fa.vue @@ -94,16 +94,12 @@ withDefaults(defineProps<{ const usePasswordLessLogin = $computed(() => $i?.usePasswordLessLogin ?? false); async function registerTOTP(): Promise { - const password = await os.inputText({ - title: i18n.ts._2fa.registerTOTP, - text: i18n.ts._2fa.passwordToTOTP, - type: 'password', - autocomplete: 'current-password', - }); - if (password.canceled) return; + const auth = await os.authenticateDialog(); + if (auth.canceled) return; const twoFactorData = await os.apiWithDialog('i/2fa/register', { - password: password.result, + password: auth.result.password, + token: auth.result.token, }); os.popup(defineAsyncComponent(() => import('./2fa.qrdialog.vue')), { @@ -111,20 +107,17 @@ async function registerTOTP(): Promise { }, {}, 'closed'); } -function unregisterTOTP(): void { - os.inputText({ - title: i18n.ts.password, - type: 'password', - autocomplete: 'current-password', - }).then(({ canceled, result: password }) => { - if (canceled) return; - os.apiWithDialog('i/2fa/unregister', { - password: password, - }).catch(error => { - os.alert({ - type: 'error', - text: error, - }); +async function unregisterTOTP(): Promise { + const auth = await os.authenticateDialog(); + if (auth.canceled) return; + + os.apiWithDialog('i/2fa/unregister', { + password: auth.result.password, + token: auth.result.token, + }).catch(error => { + os.alert({ + type: 'error', + text: error, }); }); } @@ -150,15 +143,12 @@ async function unregisterKey(key) { }); if (confirm.canceled) return; - const password = await os.inputText({ - title: i18n.ts.password, - type: 'password', - autocomplete: 'current-password', - }); - if (password.canceled) return; + const auth = await os.authenticateDialog(); + if (auth.canceled) return; await os.apiWithDialog('i/2fa/remove-key', { - password: password.result, + password: auth.result.password, + token: auth.result.token, credentialId: key.id, }); os.success(); @@ -181,16 +171,13 @@ async function renameKey(key) { } async function addSecurityKey() { - const password = await os.inputText({ - title: i18n.ts.password, - type: 'password', - autocomplete: 'current-password', - }); - if (password.canceled) return; + const auth = await os.authenticateDialog(); + if (auth.canceled) return; const registrationOptions = parseCreationOptionsFromJSON({ publicKey: await os.apiWithDialog('i/2fa/register-key', { - password: password.result, + password: auth.result.password, + token: auth.result.token, }), }); @@ -211,8 +198,12 @@ async function addSecurityKey() { ); if (!credential) return; + const auth2 = await os.authenticateDialog(); + if (auth2.canceled) return; + await os.apiWithDialog('i/2fa/key-done', { - password: password.result, + password: auth.result.password, + token: auth.result.token, name: name.result, credential: credential.toJSON(), }); diff --git a/packages/frontend/src/pages/settings/email.vue b/packages/frontend/src/pages/settings/email.vue index 1a70c3dbfb..82b7f0ae4c 100644 --- a/packages/frontend/src/pages/settings/email.vue +++ b/packages/frontend/src/pages/settings/email.vue @@ -67,18 +67,16 @@ const onChangeReceiveAnnouncementEmail = (v) => { }); }; -const saveEmailAddress = () => { - os.inputText({ - title: i18n.ts.password, - type: 'password', - }).then(({ canceled, result: password }) => { - if (canceled) return; - os.apiWithDialog('i/update-email', { - password: password, - email: emailAddress.value, - }); +async function saveEmailAddress() { + const auth = await os.authenticateDialog(); + if (auth.canceled) return; + + os.apiWithDialog('i/update-email', { + password: auth.result.password, + token: auth.result.token, + email: emailAddress.value, }); -}; +} const emailNotification_mention = ref($i!.emailNotificationTypes.includes('mention')); const emailNotification_reply = ref($i!.emailNotificationTypes.includes('reply')); diff --git a/packages/frontend/src/pages/settings/other.vue b/packages/frontend/src/pages/settings/other.vue index c3278c22f3..e2fc021099 100644 --- a/packages/frontend/src/pages/settings/other.vue +++ b/packages/frontend/src/pages/settings/other.vue @@ -113,14 +113,12 @@ async function deleteAccount() { if (canceled) return; } - const { canceled, result: password } = await os.inputText({ - title: i18n.ts.password, - type: 'password', - }); - if (canceled) return; + const auth = await os.authenticateDialog(); + if (auth.canceled) return; await os.apiWithDialog('i/delete-account', { - password: password, + password: auth.result.password, + token: auth.result.token, }); await os.alert({ diff --git a/packages/frontend/src/pages/settings/security.vue b/packages/frontend/src/pages/settings/security.vue index 7b04ab974b..eacd34778d 100644 --- a/packages/frontend/src/pages/settings/security.vue +++ b/packages/frontend/src/pages/settings/security.vue @@ -55,13 +55,6 @@ const pagination = { }; async function change() { - const { canceled: canceled1, result: currentPassword } = await os.inputText({ - title: i18n.ts.currentPassword, - type: 'password', - autocomplete: 'current-password', - }); - if (canceled1) return; - const { canceled: canceled2, result: newPassword } = await os.inputText({ title: i18n.ts.newPassword, type: 'password', @@ -84,21 +77,23 @@ async function change() { return; } + const auth = await os.authenticateDialog(); + if (auth.canceled) return; + os.apiWithDialog('i/change-password', { - currentPassword, + currentPassword: auth.result.password, + token: auth.result.token, newPassword, }); } -function regenerateToken() { - os.inputText({ - title: i18n.ts.password, - type: 'password', - }).then(({ canceled, result: password }) => { - if (canceled) return; - os.api('i/regenerate-token', { - password: password, - }); +async function regenerateToken() { + const auth = await os.authenticateDialog(); + if (auth.canceled) return; + + os.api('i/regenerate-token', { + password: auth.result.password, + token: auth.result.token, }); } -- cgit v1.2.3-freya