From 54475ba8d6fc0529870d94d591093ae5fa2d6da8 Mon Sep 17 00:00:00 2001 From: Angel Hernandez Date: Fri, 18 Oct 2024 11:18:45 -0400 Subject: [PATCH 1/3] chore: update component logic and styles --- src/components/MFA/EnableMFA.js | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/components/MFA/EnableMFA.js b/src/components/MFA/EnableMFA.js index c724c57..0a83299 100644 --- a/src/components/MFA/EnableMFA.js +++ b/src/components/MFA/EnableMFA.js @@ -1,4 +1,4 @@ -import React, { useCallback, useContext, useState } from "react"; +import React, { useContext, useState } from "react"; import { magic } from "../../lib/magic"; import { QRCode } from "react-qrcode-logo"; import authy from "../../SVG/Authy.svg"; @@ -10,7 +10,6 @@ import MFAOTPModal from "./MFAOTPModal"; export default function EnableMFA({ setShowMFASettings }) { const { user, setUser } = useContext(UserContext); - const [passcode, setPasscode] = useState(""); const [disabled, setDisabled] = useState(false); const [mfaHandle, setMFAHandle] = useState(undefined); const [mfaKey, setMFAKey] = useState(); @@ -20,7 +19,7 @@ export default function EnableMFA({ setShowMFASettings }) { const handleCancel = () => { try { - mfaHandle.emit("cancel-mfa-setup"); + mfaHandle && mfaHandle.emit("cancel-mfa-setup"); setDisabled(false); setShowMFASettings(false); @@ -33,24 +32,24 @@ export default function EnableMFA({ setShowMFASettings }) { } }; - const handleNext = () => { + const handleNext = async () => { if (mfaPage === 0) { handleEnableMFA(); setMFAPage((current) => current + 1); } else if (mfaPage === 1) { setMFAPage((current) => current + 1); - } else if (mfaPage === 2) { - mfaHandle.emit("verify-mfa-code", Number(passcode)); } else { setMFAHandle(null); setShowMFASettings(false); + + // update user info now that user.isMFAEnabled is true + const updatedUserInfo = await magic.user.getInfo(); + setUser(updatedUserInfo); } }; - const handleEnableMFA = useCallback(async () => { + const handleEnableMFA = async () => { try { - setPasscode(""); - const mfaHandle = magic.user.enableMFA({ showUI: false }); setMFAHandle(mfaHandle); @@ -67,10 +66,6 @@ export default function EnableMFA({ setShowMFASettings }) { setRecoveryCode(recoveryCode); setMFAPage((currentPage) => currentPage + 1); - - // update user info now that user.isMFAEnabled is true - const updatedUserInfo = await magic.user.getInfo(); - setUser(updatedUserInfo); }) .on("error", (error) => { console.log("error configuring MFA"); @@ -80,7 +75,7 @@ export default function EnableMFA({ setShowMFASettings }) { console.error(error); setShowMFASettings(false); } - }, [setShowMFASettings]); + }; const copyToClipboard = (text) => { navigator.clipboard @@ -184,6 +179,8 @@ export default function EnableMFA({ setShowMFASettings }) {
+ Your recovery code + copyToClipboard(recoveryCode)} @@ -195,7 +192,6 @@ export default function EnableMFA({ setShowMFASettings }) { className="copy-symbol-svg" /> - Your recovery code
)} From b77f2a0dca506a2fd6fce715ab8c96d9f2e66fae Mon Sep 17 00:00:00 2001 From: Angel Hernandez Date: Fri, 18 Oct 2024 11:20:15 -0400 Subject: [PATCH 2/3] feat: add disable MFA --- src/App.js | 7 +- src/components/MFA/DisableMFA.js | 120 +++++++++++++++++++++++++++++++ src/index.css | 23 +++++- 3 files changed, 146 insertions(+), 4 deletions(-) create mode 100644 src/components/MFA/DisableMFA.js diff --git a/src/App.js b/src/App.js index 533d7b3..04eb29b 100644 --- a/src/App.js +++ b/src/App.js @@ -11,6 +11,7 @@ import Footer from "./components/Footer.js"; import ShowSettings from "./components/MFA/ShowSettings.js"; import EnableMFA from "./components/MFA/EnableMFA.js"; import UserContext from "./context/UserContext.js"; +import DisableMFA from "./components/MFA/DisableMFA.js"; function App() { const { user, setUser } = useContext(UserContext); @@ -60,10 +61,10 @@ function App() { )} {showMFASettings === true ? ( - !user.ismfaEnabled ? ( - + user.isMfaEnabled ? ( + ) : ( - "DISABLE MFA PLACEHOLDER" + ) ) : ( "" diff --git a/src/components/MFA/DisableMFA.js b/src/components/MFA/DisableMFA.js new file mode 100644 index 0000000..7d69701 --- /dev/null +++ b/src/components/MFA/DisableMFA.js @@ -0,0 +1,120 @@ +import React, { useCallback, useContext, useState } from "react"; +import { magic } from "../../lib/magic"; +import UserContext from "../../context/UserContext"; +import MFAOTPModal from "./MFAOTPModal"; +import authy from "../../SVG/Authy.svg"; +import googleAuth from "../../SVG/GoogleAuthenticator.svg"; + +export default function DisableMFA({ setShowMFASettings }) { + const { user, setUser } = useContext(UserContext); + const [disabled, setDisabled] = useState(false); + const [mfaHandle, setMFAHandle] = useState(undefined); + const [mfaPage, setMFAPage] = useState(0); + + const handleCancel = useCallback(() => { + try { + mfaHandle && mfaHandle.emit("cancel-mfa-disable"); + setDisabled(false); + setShowMFASettings(false); + setMFAHandle(undefined); + console.log("%cUser canceled MFA setup", "color: orange"); + } catch (err) { + console.log("Error canceling MFA setup"); + console.error(err); + } + }, [mfaHandle, setShowMFASettings]); + + const handleNext = async () => { + if (mfaPage === 0) { + handleDisableMFA(); + setMFAPage((current) => current + 1); + } else { + setShowMFASettings(false); + setMFAHandle(undefined); + + // update user info now that user.isMFAEnabled is true + const updatedUserInfo = await magic.user.getInfo(); + setUser(updatedUserInfo); + } + }; + + const handleDisableMFA = () => { + const mfaHandle = magic.user.disableMFA({ showUI: false }); + setMFAHandle(mfaHandle); + mfaHandle + .on("mfa-code-requested", () => { + // Dispatched when the user starts the disable MFA process. + console.log("mfa-code-requested"); + }) + .on("done", async () => { + // MFA disabled successfully. + console.log("MFA disabled successfully"); + setMFAPage((currentPage) => currentPage + 1); + }) + .on("error", (error) => { + console.log("error configuring MFA"); + console.error(error); + setMFAHandle(undefined); + setShowMFASettings(false); + }); + }; + + return ( +
+
+
+ {mfaPage === 0 && ( + <> +
+
+ Authy logo + Google Authenticator logo +
+

You'll need your authenticator app

+
+ +
+ To disable multi-factor authentication, you will need to use the + authenticator app you used to enable MFA, such as{" "} + Authy or{" "} + + Google Authenticator + + . +
+ + )} + + {mfaPage === 1 && ( + + )} + + {mfaPage === 2 && ( + <> +
+

You disabled MFA!

+
👍
+
+ + )} + + {mfaPage !== 1 && ( +
+ +
+ )} +
+
+
+ ); +} diff --git a/src/index.css b/src/index.css index f93d6fb..7fb3b7e 100644 --- a/src/index.css +++ b/src/index.css @@ -587,7 +587,6 @@ td { .key-wrapper { display: flex; - flex-direction: column; justify-content: space-between; gap: 0.5em; margin: auto; @@ -606,6 +605,12 @@ td { background-color: #f7f7ff; cursor: pointer; } +.span-recovery { + display: flex; + flex-direction: column; + justify-content: space-around; + color: var(--color-palette-4); +} .span-key-wrapper { display: flex; flex-direction: column; @@ -613,6 +618,22 @@ td { color: var(--color-palette-1); } +.emoji-confirm { + width: 100px; + height: 100px; + display: flex; + flex-direction: column; + justify-content: space-around; + color: var(--color-palette-3); + + margin: auto; + border-radius: 10px; + padding: 1em; + + background-color: #495867; + font-size: xx-large; +} + .span-page3-wrapper { display: flex; flex-direction: column; From da879d83454b09b1ac18a8a3ca28edd6bfb2b1c5 Mon Sep 17 00:00:00 2001 From: Angel Hernandez Date: Fri, 18 Oct 2024 11:20:56 -0400 Subject: [PATCH 3/3] chore: update MFAOTPModal --- src/components/MFA/MFAOTPModal.js | 59 +++++++++++++++++-------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/src/components/MFA/MFAOTPModal.js b/src/components/MFA/MFAOTPModal.js index fa0aaf1..a04d3e2 100644 --- a/src/components/MFA/MFAOTPModal.js +++ b/src/components/MFA/MFAOTPModal.js @@ -7,38 +7,45 @@ export default function MFAOTPModal({ handle, handleCancel }) { const [disabled, setDisabled] = useState(false); const handleSubmit = async (e) => { - e.preventDefault(); + try { + e.preventDefault(); - setDisabled(true); - setRetries((r) => r - 1); - setPasscode(""); + setDisabled(true); + setRetries((r) => r - 1); + setPasscode(""); - // Send MFA OTP for verification - handle.emit("verify-mfa-code", passcode); + // Send MFA OTP for verification + handle.emit("verify-mfa-code", passcode); - handle.on("invalid-mfa-otp", (res) => { - console.log("invalid-mfa-otp"); + handle + .on("invalid-mfa-otp", (res) => { + if (res && res.errorCode) { + console.log("Error code:", res.errorCode); + } - if (res && res.errorCode) { - console.log("Error code:", res.errorCode); - } + // User entered invalid MFA OTP + setDisabled(false); - // User entered invalid MFA OTP - setDisabled(false); + if (!retries) { + setMessage("No more retries. Please try again later."); - if (!retries) { - setMessage("No more retries. Please try again later."); - - handleCancel(); - } else { - // Prompt the user again for the MFA OTP - setMessage( - `Incorrect code. Please enter MFA OTP again. ${retries} ${ - retries === 1 ? "retry" : "retries" - } left.` - ); - } - }); + handleCancel(); + } else { + // Prompt the user again for the MFA OTP + setMessage( + `Incorrect code. Please enter MFA OTP again. ${retries} ${ + retries === 1 ? "retry" : "retries" + } left.` + ); + } + }) + .on("error", (err) => { + console.error(err); + }); + } catch (err) { + console.log("Error submitting MFA OTP"); + console.error(err); + } }; return (