From 028ed05973083c6afe3d838d9dbb7e9847bb1408 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Wed, 8 Mar 2023 14:51:52 +0530 Subject: [PATCH] Disable 2FA recovery --- src/constants/pages/index.ts | 1 - src/pages/two-factor/recover/index.tsx | 121 ------------------------- src/pages/two-factor/setup/index.tsx | 6 +- src/pages/two-factor/verify/index.tsx | 15 ++- src/services/userService.ts | 26 +----- src/types/user/index.ts | 5 - yarn.lock | 93 +------------------ 7 files changed, 17 insertions(+), 250 deletions(-) delete mode 100644 src/pages/two-factor/recover/index.tsx diff --git a/src/constants/pages/index.ts b/src/constants/pages/index.ts index cd5f3b0e6..e8612b3fd 100644 --- a/src/constants/pages/index.ts +++ b/src/constants/pages/index.ts @@ -9,7 +9,6 @@ export enum PAGES { SIGNUP = '/signup', TWO_FACTOR_SETUP = '/two-factor/setup', TWO_FACTOR_VERIFY = '/two-factor/verify', - TWO_FACTOR_RECOVER = '/two-factor/recover', VERIFY = '/verify', ROOT = '/', SHARED_ALBUMS = '/shared-albums', diff --git a/src/pages/two-factor/recover/index.tsx b/src/pages/two-factor/recover/index.tsx deleted file mode 100644 index 9503162f0..000000000 --- a/src/pages/two-factor/recover/index.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import React, { useContext, useEffect, useState } from 'react'; -import constants from 'utils/strings/constants'; -import { getData, LS_KEYS, setData } from 'utils/storage/localStorage'; -import { useRouter } from 'next/router'; -import SingleInputForm, { - SingleInputFormProps, -} from 'components/SingleInputForm'; -import VerticallyCentered from 'components/Container'; -import { logError } from 'utils/sentry'; -import { recoverTwoFactor, removeTwoFactor } from 'services/userService'; -import { AppContext } from 'pages/_app'; -import { PAGES } from 'constants/pages'; -import FormPaper from 'components/Form/FormPaper'; -import FormPaperTitle from 'components/Form/FormPaper/Title'; -import FormPaperFooter from 'components/Form/FormPaper/Footer'; -import LinkButton from 'components/pages/gallery/LinkButton'; -import { B64EncryptionResult } from 'types/crypto'; -import ComlinkCryptoWorker from 'utils/comlink/ComlinkCryptoWorker'; -const bip39 = require('bip39'); -// mobile client library only supports english. -bip39.setDefaultWordlist('english'); - -export default function Recover() { - const router = useRouter(); - const [encryptedTwoFactorSecret, setEncryptedTwoFactorSecret] = - useState(null); - const [sessionID, setSessionID] = useState(null); - const appContext = useContext(AppContext); - - useEffect(() => { - router.prefetch(PAGES.GALLERY); - const user = getData(LS_KEYS.USER); - if (!user.isTwoFactorEnabled && (user.encryptedToken || user.token)) { - router.push(PAGES.GENERATE); - } else if (!user.email || !user.twoFactorSessionID) { - router.push(PAGES.ROOT); - } else { - setSessionID(user.twoFactorSessionID); - } - const main = async () => { - const resp = await recoverTwoFactor(user.twoFactorSessionID); - setEncryptedTwoFactorSecret({ - encryptedData: resp.encryptedSecret, - nonce: resp.secretDecryptionNonce, - key: null, - }); - }; - main(); - }, []); - - const recover: SingleInputFormProps['callback'] = async ( - recoveryKey: string, - setFieldError - ) => { - try { - recoveryKey = recoveryKey - .trim() - .split(' ') - .map((part) => part.trim()) - .filter((part) => !!part) - .join(' '); - // check if user is entering mnemonic recovery key - if (recoveryKey.indexOf(' ') > 0) { - if (recoveryKey.split(' ').length !== 24) { - throw new Error('recovery code should have 24 words'); - } - recoveryKey = bip39.mnemonicToEntropy(recoveryKey); - } - const cryptoWorker = await ComlinkCryptoWorker.getInstance(); - const twoFactorSecret = await cryptoWorker.decryptB64( - encryptedTwoFactorSecret.encryptedData, - encryptedTwoFactorSecret.nonce, - await cryptoWorker.fromHex(recoveryKey) - ); - const resp = await removeTwoFactor(sessionID, twoFactorSecret); - const { keyAttributes, encryptedToken, token, id } = resp; - setData(LS_KEYS.USER, { - ...getData(LS_KEYS.USER), - token, - encryptedToken, - id, - isTwoFactorEnabled: false, - }); - setData(LS_KEYS.KEY_ATTRIBUTES, keyAttributes); - router.push(PAGES.CREDENTIALS); - } catch (e) { - logError(e, 'two factor recovery failed'); - setFieldError(constants.INCORRECT_RECOVERY_KEY); - } - }; - - const showNoRecoveryKeyMessage = () => { - appContext.setDialogMessage({ - title: constants.CONTACT_SUPPORT, - close: {}, - content: constants.NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE(), - }); - }; - - return ( - - - {constants.RECOVER_TWO_FACTOR} - - - - {constants.NO_RECOVERY_KEY} - - - {constants.GO_BACK} - - - - - ); -} diff --git a/src/pages/two-factor/setup/index.tsx b/src/pages/two-factor/setup/index.tsx index 7b32a2c9f..b595948c6 100644 --- a/src/pages/two-factor/setup/index.tsx +++ b/src/pages/two-factor/setup/index.tsx @@ -6,7 +6,6 @@ import { useRouter } from 'next/router'; import VerifyTwoFactor, { VerifyTwoFactorCallback, } from 'components/TwoFactor/VerifyForm'; -import { encryptWithRecoveryKey } from 'utils/crypto'; import { setData, LS_KEYS, getData } from 'utils/storage/localStorage'; import { PAGES } from 'constants/pages'; import { TwoFactorSecret } from 'types/user'; @@ -45,10 +44,7 @@ export default function SetupTwoFactor() { otp: string, markSuccessful ) => { - const recoveryEncryptedTwoFactorSecret = await encryptWithRecoveryKey( - twoFactorSecret.secretCode - ); - await enableTwoFactor(otp, recoveryEncryptedTwoFactorSecret); + await enableTwoFactor(otp); await markSuccessful(); setData(LS_KEYS.USER, { ...getData(LS_KEYS.USER), diff --git a/src/pages/two-factor/verify/index.tsx b/src/pages/two-factor/verify/index.tsx index de393d3bf..aea96e42f 100644 --- a/src/pages/two-factor/verify/index.tsx +++ b/src/pages/two-factor/verify/index.tsx @@ -2,8 +2,9 @@ import VerifyTwoFactor, { VerifyTwoFactorCallback, } from 'components/TwoFactor/VerifyForm'; import router from 'next/router'; -import React, { useEffect, useState } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; import { logoutUser, verifyTwoFactor } from 'services/userService'; +import { AppContext } from 'pages/_app'; import { PAGES } from 'constants/pages'; import { User } from 'types/user'; import { setData, LS_KEYS, getData } from 'utils/storage/localStorage'; @@ -16,6 +17,7 @@ import FormPaperFooter from 'components/Form/FormPaper/Footer'; export default function Home() { const [sessionID, setSessionID] = useState(''); + const appContext = useContext(AppContext); useEffect(() => { const main = async () => { @@ -35,6 +37,14 @@ export default function Home() { main(); }, []); + const showContactSupport = () => { + appContext.setDialogMessage({ + title: constants.CONTACT_SUPPORT, + close: {}, + content: constants.NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE(), + }); + }; + const onSubmit: VerifyTwoFactorCallback = async (otp) => { try { const resp = await verifyTwoFactor(otp, sessionID); @@ -65,8 +75,7 @@ export default function Home() { /> - router.push(PAGES.TWO_FACTOR_RECOVER)}> + {constants.LOST_DEVICE} diff --git a/src/services/userService.ts b/src/services/userService.ts index 972068aa9..1d01af508 100644 --- a/src/services/userService.ts +++ b/src/services/userService.ts @@ -15,7 +15,6 @@ import { RecoveryKey, TwoFactorSecret, TwoFactorVerificationResponse, - TwoFactorRecoveryResponse, UserDetails, DeleteChallengeResponse, GetRemoteStoreValueResponse, @@ -24,7 +23,6 @@ import { ServerErrorCodes } from 'utils/error'; import isElectron from 'is-electron'; import safeStorageService from './electron/safeStorage'; import { deleteAllCache } from 'utils/storage/cache'; -import { B64EncryptionResult } from 'types/crypto'; import { getLocalFamilyData, isPartOfFamily } from 'utils/user/family'; import { AxiosResponse } from 'axios'; @@ -219,18 +217,11 @@ export const setupTwoFactor = async () => { return resp.data as TwoFactorSecret; }; -export const enableTwoFactor = async ( - code: string, - recoveryEncryptedTwoFactorSecret: B64EncryptionResult -) => { +export const enableTwoFactor = async (code: string) => { await HTTPService.post( `${ENDPOINT}/users/two-factor/enable`, { code, - encryptedTwoFactorSecret: - recoveryEncryptedTwoFactorSecret.encryptedData, - twoFactorSecretDecryptionNonce: - recoveryEncryptedTwoFactorSecret.nonce, }, null, { @@ -251,21 +242,6 @@ export const verifyTwoFactor = async (code: string, sessionID: string) => { return resp.data as TwoFactorVerificationResponse; }; -export const recoverTwoFactor = async (sessionID: string) => { - const resp = await HTTPService.get(`${ENDPOINT}/users/two-factor/recover`, { - sessionID, - }); - return resp.data as TwoFactorRecoveryResponse; -}; - -export const removeTwoFactor = async (sessionID: string, secret: string) => { - const resp = await HTTPService.post(`${ENDPOINT}/users/two-factor/remove`, { - sessionID, - secret, - }); - return resp.data as TwoFactorVerificationResponse; -}; - export const disableTwoFactor = async () => { await HTTPService.post(`${ENDPOINT}/users/two-factor/disable`, null, null, { 'X-Auth-Token': getToken(), diff --git a/src/types/user/index.ts b/src/types/user/index.ts index a02bfc0f5..5f8c1e62b 100644 --- a/src/types/user/index.ts +++ b/src/types/user/index.ts @@ -61,11 +61,6 @@ export interface TwoFactorSecret { qrCode: string; } -export interface TwoFactorRecoveryResponse { - encryptedSecret: string; - secretDecryptionNonce: string; -} - export interface FamilyMember { email: string; usage: number; diff --git a/yarn.lock b/yarn.lock index e7d240d2f..c89a7f57b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1340,16 +1340,6 @@ blazeface-back@^0.0.8: resolved "https://registry.yarnpkg.com/blazeface-back/-/blazeface-back-0.0.8.tgz#d997a9cfcd5b7ad03367d65d7c0b365c5a835b83" integrity sha512-7eYoSPJ9JvV2cHp+qwW+YNvrdTDFzMGnSGCGR24Lx6OluwPa+qX4NqNrBv31ukw2Ne/FkvFHhZuUDpxpowr+Bg== -blueimp-load-image@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/blueimp-load-image/-/blueimp-load-image-3.0.0.tgz#d71c39440a7d2f1a83e3e86a625e329116a51705" - integrity sha512-Q9rFbd4ZUNvzSFmRXx9MoG0RwWwJeMjjEUbG7WIOJgUg22Jgkow0wL5b35B6qwiBscxACW9OHdrP5s2vQ3x8DQ== - -bmp-js@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.1.0.tgz#e05a63f796a6c1ff25f4771ec7adadc148c07233" - integrity sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw== - bootstrap@^4.5.2: version "4.6.0" resolved "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.0.tgz" @@ -1501,11 +1491,6 @@ colorette@^1.2.2: resolved "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz" integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== -colors@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" - integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== - comlink@^4.3.0: version "4.3.1" resolved "https://registry.npmjs.org/comlink/-/comlink-4.3.1.tgz" @@ -2224,11 +2209,6 @@ file-selector@^0.2.2: dependencies: tslib "^2.0.3" -file-type@^12.4.1: - version "12.4.2" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-12.4.2.tgz#a344ea5664a1d01447ee7fb1b635f72feb6169d9" - integrity sha512-UssQP5ZgIOKelfsaB5CuGAL+Y+q7EmONuiwF3N5HAH0t27rvrttgi6Ra9k/+DVaY9UF6+ybxu5pOXLUdA8N7Vg== - file-type@^16.5.4: version "16.5.4" resolved "https://registry.yarnpkg.com/file-type/-/file-type-16.5.4.tgz#474fb4f704bee427681f98dd390058a172a6c2fd" @@ -2415,18 +2395,6 @@ glob@7.1.7, glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.6: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - globals@^11.1.0: version "11.12.0" resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" @@ -2641,11 +2609,6 @@ husky@^7.0.1: resolved "https://registry.npmjs.org/husky/-/husky-7.0.2.tgz" integrity sha512-8yKEWNX4z2YsofXAMT7KvA1g8p+GxtB1ffV8XtpAEGuXNAbCV5wdNKH+qTpw8SM9fh4aMPDR+yQuKfgnreyZlg== -idb-keyval@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/idb-keyval/-/idb-keyval-3.2.0.tgz#cbbf354deb5684b6cdc84376294fc05932845bd6" - integrity sha512-slx8Q6oywCCSfKgPgL0sEsXtPVnSbTLWpyiDcu6msHOyKOLari1TD1qocXVCft80umnkk3/Qqh3lwoFt8T/BPQ== - idb@^6.0.0: version "6.1.3" resolved "https://registry.npmjs.org/idb/-/idb-6.1.3.tgz" @@ -2995,18 +2958,7 @@ isexe@^2.0.0: resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= -jpeg-autorotate@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/jpeg-autorotate/-/jpeg-autorotate-7.1.1.tgz#c57905c6afd3b54373a6a1d0249ed6e07f7b043b" - integrity sha512-ewTZTG/QWOM0D5h/yKcQ3QgyrnQYsr3qmcS+bqoAwgQAY1KBa31aJ+q+FlElaxo/rSYqfF1ixf+8EIgluBkgTg== - dependencies: - colors "^1.4.0" - glob "^7.1.6" - jpeg-js "^0.4.2" - piexifjs "^1.0.6" - yargs-parser "^20.2.1" - -jpeg-js@^0.4.1, jpeg-js@^0.4.2: +jpeg-js@^0.4.1: version "0.4.4" resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.4.tgz#a9f1c6f1f9f0fa80cdb3484ed9635054d28936aa" integrity sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg== @@ -3547,11 +3499,6 @@ open@^8.4.0: is-docker "^2.1.1" is-wsl "^2.2.0" -opencollective-postinstall@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259" - integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q== - opener@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" @@ -3991,7 +3938,7 @@ regenerator-runtime@^0.13.11: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== -regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: +regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: version "0.13.9" resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz" integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== @@ -4020,11 +3967,6 @@ resolve-from@^4.0.0: resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== - resolve@^1.20.0: version "1.20.0" resolved "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz" @@ -4484,27 +4426,8 @@ tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -tesseract.js-core@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/tesseract.js-core/-/tesseract.js-core-2.2.0.tgz#6ef78051272a381969fac3e45a226e85022cffef" - integrity sha512-a8L+OJTbUipBsEDsJhDPlnLB0TY1MkTZqw5dqUwmiDSjUzwvU7HWLg/2+WDRulKUi4LE+7PnHlaBlW0k+V0U0w== - "tesseract.js@file:./thirdparty/tesseract": - version "2.1.5" - dependencies: - blueimp-load-image "^3.0.0" - bmp-js "^0.1.0" - file-type "^12.4.1" - idb-keyval "^3.2.0" - is-electron "^2.2.0" - is-url "^1.2.4" - jpeg-autorotate "^7.1.1" - node-fetch "^2.6.0" - opencollective-postinstall "^2.0.2" - regenerator-runtime "^0.13.3" - resolve-url "^0.2.1" - tesseract.js-core "^2.2.0" - zlibjs "^0.3.1" + version "0.0.0" text-table@^0.2.0: version "0.2.0" @@ -4881,11 +4804,6 @@ yaml@^1.10.0: resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== -yargs-parser@^20.2.1: - version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== - yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" @@ -4904,11 +4822,6 @@ yup@^0.29.3: synchronous-promise "^2.0.13" toposort "^2.0.2" -zlibjs@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/zlibjs/-/zlibjs-0.3.1.tgz#50197edb28a1c42ca659cc8b4e6a9ddd6d444554" - integrity sha512-+J9RrgTKOmlxFSDHo0pI1xM6BLVUv+o0ZT9ANtCxGkjIVCCUdx9alUF8Gm+dGLKbkkkidWIHFDZHDMpfITt4+w== - zxcvbn@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/zxcvbn/-/zxcvbn-4.4.2.tgz#28ec17cf09743edcab056ddd8b1b06262cc73c30"