{
    "componentChunkName": "component---src-pages-blog-markdown-remark-fields-slug-js",
    "path": "/blog/phishing-resistant-mfa",
    "result": {"data":{"markdownRemark":{"html":"<h2 id=\"why-traditional-multi-factor-authentication-mfa-is-no-longer-enough\" style=\"position:relative;\"><a href=\"#why-traditional-multi-factor-authentication-mfa-is-no-longer-enough\" aria-label=\"why traditional multi factor authentication mfa is no longer enough permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why Traditional Multi-Factor Authentication (MFA) Is No Longer Enough</h2>\n<p>Multi-factor authentication has become a standard security recommendation, but not all MFA implementations are created equal. Traditional MFA methods, despite adding a security layer beyond passwords, contain critical vulnerabilities that sophisticated attackers regularly exploit. Traditional MFA methods - SMS codes, authenticator apps with time-based one-time passwords (TOTPs), and even email verification have proven vulnerable to sophisticated phishing attacks.</p>\n<h2 id=\"why-traditional-mfa-fails\" style=\"position:relative;\"><a href=\"#why-traditional-mfa-fails\" aria-label=\"why traditional mfa fails permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why Traditional MFA Fails</h2>\n<h3 id=\"sim-swapping-when-your-phone-number-betrays-you\" style=\"position:relative;\"><a href=\"#sim-swapping-when-your-phone-number-betrays-you\" aria-label=\"sim swapping when your phone number betrays you permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>SIM Swapping: When Your Phone Number Betrays You</h3>\n<p>This attack occurs when bad actors convince mobile carriers to transfer a victim’s phone number to a device they control. Once successful, they can intercept SMS-based verification codes meant for the legitimate user. This isn’t some obscure practice either, in 2022 CEO of Transform Ventures Michael Terpin <a href=\"https://commsrisk.com/the-story-of-a-24mn-sim-swap/\" target=\"_blank\" rel=\"nofollow\">won a $75 million lawsuit against a SIM-swapping perpetrator who stole millions in digital assets</a> by hijacking his phone number. More information can be found on our dedicated <a href=\"https://supertokens.com/blog/sim-swapping\" target=\"_blank\" rel=\"nofollow\">SIM Swapping Post</a>.</p>\n<h3 id=\"phishing-for-credentials\" style=\"position:relative;\"><a href=\"#phishing-for-credentials\" aria-label=\"phishing for credentials permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Phishing For Credentials</h3>\n<p>Even app-based authenticators like Google Authenticator or Authy can be compromised through well-crafted phishing campaigns. In 2023, the MGM Resorts cyberattack caused <a href=\"https://thrivedx.com/resources/article/investigating-the-mgm-cyberattack-how-social-engineering-and-a-help-desk-put-the-whole-strip-at-risk\" target=\"_blank\" rel=\"nofollow\">an estimated $100 million in damages</a> despite having MFA in place. A group of bad actors used social engineering to manipulate MGM help desk employees into resetting MFA settings, granting them access to terabytes of data.</p>\n<h3 id=\"social-engineering-exploiting-the-human\" style=\"position:relative;\"><a href=\"#social-engineering-exploiting-the-human\" aria-label=\"social engineering exploiting the human permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Social Engineering: Exploiting the Human</h3>\n<p>Human psychology remains the weakest link in security systems. The widely documented “0ktapus” campaign <a href=\"https://group-ib.com/blog/0ktapus/\" target=\"_blank\" rel=\"nofollow\">successfully targeted over 130 organizations</a>, as reported by cybersecurity firm Group-IB, would target employees with convincing Okta login pages to steal credentials in real time. Victims who clicked the links and entered their credentials and MFA codes inadvertently gave attackers access to their corporate accounts, leading to significant data breaches at companies like Twilio and Cloudflare. Cloudflare’s <a href=\"https://blog.cloudflare.com/2022-07-sms-phishing-attacks/\" target=\"_blank\" rel=\"nofollow\">own security incident report</a> noted that employees using FIDO2-based hardware security keys remained protected while those using push notifications were compromised.</p>\n<h2 id=\"what-makes-mfa-phishing-resistant\" style=\"position:relative;\"><a href=\"#what-makes-mfa-phishing-resistant\" aria-label=\"what makes mfa phishing resistant permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What Makes MFA Phishing-Resistant?</h2>\n<p>The core issue? These methods rely on shared secrets that can be intercepted or stolen. Phishing-resistant MFA eliminates reliance on shared secrets by leveraging asymmetric cryptography and binding authentication to specific origins (websites). This fundamentally changes the security model:</p>\n<ul>\n<li>Authentication is bound to specific domains, preventing credential reuse across different sites</li>\n<li>Private keys never leave the user’s device</li>\n<li>Biometric or physical presence verification ensures the legitimate user is present</li>\n</ul>\n<p>In this guide, we’ll implement a bulletproof phishing-resistant MFA system using SuperTokens, WebAuthn, and FIDO2 standards. This approach not only strengthens security but also improves user experience by reducing friction.</p>\n<h3 id=\"why-webauthn\" style=\"position:relative;\"><a href=\"#why-webauthn\" aria-label=\"why webauthn permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why WebAuthn?</h3>\n<p>Phishing remains one of the most effective attack vectors against traditional authentication. WebAuthn counters this by binding authentication directly to the user’s device through public-key cryptography. When users register with WebAuthn, their device generates a unique key pair for that service. The private key never leaves the device, while the public key is stored on the server. During authentication, the server sends a challenge only the correct private key can sign.</p>\n<p>The critical phishing protection comes from origin binding - the browser ensures authentication requests can only come from the exact domain that registered the credential. Even perfect site clones at different URLs will fail because the origins don’t match. For developers, this means implementing authentication that protects users regardless of their susceptibility to phishing attempts.</p>\n<h3 id=\"how-webauthn-works\" style=\"position:relative;\"><a href=\"#how-webauthn-works\" aria-label=\"how webauthn works permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How WebAuthn works</h3>\n<p>WebAuthn creates a secure authentication framework built on asymmetric cryptography. Instead of storing shared secrets like passwords on servers, it employs public-private key pairs. When users register their device generates these unique keys - the private key remains secured on the device while the public key is stored on the server.The absence of passwords eliminates common vulnerabilities like credential stuffing, password spraying, and database breaches. There’s simply no password to steal, reuse, or crack, removing entire categories of attacks from consideration.</p>\n<p>User verification happens locally on the device through either biometrics (fingerprints, facial recognition) or hardware security keys. This verification proves the legitimate user is present without transmitting biometric data to the server. The local device handles all sensitive verification, then cryptographically signs the authentication challenge using the private key only after successful verification.</p>\n<h2 id=\"prerequisites--what-you-need-to-get-started\" style=\"position:relative;\"><a href=\"#prerequisites--what-you-need-to-get-started\" aria-label=\"prerequisites  what you need to get started permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Prerequisites – What You Need to Get Started</h2>\n<p>Before diving into implementation, ensure you have:</p>\n<ul>\n<li>SuperTokens Core and a backend sdk installed (we’ll cover a quick setup if you haven’t)</li>\n<li>A WebAuthn-supported browser (Chrome, Firefox, Edge, Safari all have excellent support)</li>\n<li>A FIDO2 security key (YubiKey, SoloKey) or device with built-in biometric authentication (Windows Hello, Face ID, Touch ID)</li>\n<li>A basic web application (we’ll use React/Node.js, but the concepts apply to other stacks)</li>\n</ul>\n<p>Let’s get started with a robust implementation that will protect your users from even the most sophisticated phishing attempts.</p>\n<h2 id=\"step-1--setting-up-supertokens-for-authentication\" style=\"position:relative;\"><a href=\"#step-1--setting-up-supertokens-for-authentication\" aria-label=\"step 1  setting up supertokens for authentication permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Step 1 – Setting Up SuperTokens for Authentication</strong></h2>\n<ul>\n<li>\n<p>Installing SuperTokens Core and Backend SDK. More details about the Core service and SDKs can be found at the Supertokens docs - <a href=\"https://supertokens.com/docs/quickstart/introduction\" target=\"_blank\" rel=\"nofollow\">here</a></p>\n<p><code class=\"language-text\">npx create-supertokens-app@latest --recipe=emailpassword</code></p>\n</li>\n<li>\n<p>Once everything has finished installing <code class=\"language-text\">cd</code> into the new project directory and run <code class=\"language-text\">npm start</code>. Visit <a href=\"http://localhost:3000\" target=\"_blank\" rel=\"nofollow\"><code class=\"language-text\">http://localhost:3000/auth</code></a> in your browser to see the demo app working.</p>\n</li>\n</ul>\n<h2 id=\"step-2--enabling-webauthn-for-passwordless-phishing-resistant-mfa\" style=\"position:relative;\"><a href=\"#step-2--enabling-webauthn-for-passwordless-phishing-resistant-mfa\" aria-label=\"step 2  enabling webauthn for passwordless phishing resistant mfa permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Step 2 – Enabling WebAuthn for Passwordless, Phishing-Resistant MFA</strong></h2>\n<h3 id=\"implementation\" style=\"position:relative;\"><a href=\"#implementation\" aria-label=\"implementation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Implementation</h3>\n<p>Note: Any project structure is based on the used cli command from above</p>\n<p>We’ll be using the WebAuthn Recipe, <a href=\"https://supertokens.com/docs/authentication/passkeys/initial-setup\" target=\"_blank\" rel=\"nofollow\">more information at the quickstart guide</a>. First update the frontend, find the <code class=\"language-text\">config.tsx</code> file located in <code class=\"language-text\">/frontend/src/config.tsx</code>.</p>\n<ul>\n<li>Import <code class=\"language-text\">WebAuthn</code> from the recipe</li>\n<li>Update the <code class=\"language-text\">recipeList</code> for <code class=\"language-text\">SuperTokensConfig</code></li>\n<li>Update the <code class=\"language-text\">PreBuiltUIList</code> to include <code class=\"language-text\">WebauthnPreBuiltUI</code></li>\n</ul>\n<p>You’re file should look like the following:</p>\n<p>Frontend <code class=\"language-text\">config.tsx</code></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"53041110033076675000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`\nimport EmailPassword from &quot;supertokens-auth-react/recipe/emailpassword&quot;;\nimport { EmailPasswordPreBuiltUI } from &quot;supertokens-auth-react/recipe/emailpassword/prebuiltui&quot;;\nimport Session from &quot;supertokens-auth-react/recipe/session&quot;;\n\nimport WebAuthn from &quot;supertokens-auth-react/recipe/webauthn&quot;; // passkeys\nimport { WebauthnPreBuiltUI } from 'supertokens-auth-react/recipe/webauthn/prebuiltui'; // passkeys\n\n\nexport function getApiDomain() {\n    const apiPort = import.meta.env.VITE_APP_API_PORT || 3001;\n    const apiUrl = import.meta.env.VITE_APP_API_URL || \\`http://localhost:\\${apiPort}\\`;\n    return apiUrl;\n}\n\nexport function getWebsiteDomain() {\n    const websitePort = import.meta.env.VITE_APP_WEBSITE_PORT || 3000;\n    const websiteUrl = import.meta.env.VITE_APP_WEBSITE_URL || \\`http://localhost:\\${websitePort}\\`;\n    return websiteUrl;\n}\n\nexport const SuperTokensConfig = {\n    appInfo: {\n        appName: &quot;SuperTokens Demo App&quot;,\n        apiDomain: getApiDomain(),\n        websiteDomain: getWebsiteDomain(),\n    },\n    // recipeList contains all the modules that you want to\n    // use from SuperTokens. See the full list here: https://supertokens.com/docs/guides\n    recipeList: [\n        EmailPassword.init(),\n        WebAuthn.init(),\n        Session.init()\n    ],\n    getRedirectionURL: async (context) => {\n        if (context.action === &quot;SUCCESS&quot; && context.newSessionCreated) {\n            return &quot;/dashboard&quot;;\n        }\n    },\n};\n\nexport const recipeDetails = {\n    docsLink: &quot;https://supertokens.com/docs/emailpassword/introduction&quot;,\n};\n\nexport const PreBuiltUIList = [\n    EmailPasswordPreBuiltUI,\n    WebauthnPreBuiltUI,\n];\n\nexport const ComponentWrapper = (props: { children: JSX.Element }): JSX.Element => {\n    return props.children;\n};`, `53041110033076675000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">\n<span class=\"token keyword\">import</span> EmailPassword <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/emailpassword\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> EmailPasswordPreBuiltUI <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/emailpassword/prebuiltui\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> Session <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/session\"</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">import</span> WebAuthn <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/webauthn\"</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// passkeys</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> WebauthnPreBuiltUI <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'supertokens-auth-react/recipe/webauthn/prebuiltui'</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// passkeys</span>\n\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">function</span> <span class=\"token function\">getApiDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> apiPort <span class=\"token operator\">=</span> <span class=\"token keyword\">import</span><span class=\"token punctuation\">.</span>meta<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_APP_API_PORT</span> <span class=\"token operator\">||</span> <span class=\"token number\">3001</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> apiUrl <span class=\"token operator\">=</span> <span class=\"token keyword\">import</span><span class=\"token punctuation\">.</span>meta<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_APP_API_URL</span> <span class=\"token operator\">||</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">http://localhost:</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>apiPort<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> apiUrl<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">function</span> <span class=\"token function\">getWebsiteDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> websitePort <span class=\"token operator\">=</span> <span class=\"token keyword\">import</span><span class=\"token punctuation\">.</span>meta<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_APP_WEBSITE_PORT</span> <span class=\"token operator\">||</span> <span class=\"token number\">3000</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> websiteUrl <span class=\"token operator\">=</span> <span class=\"token keyword\">import</span><span class=\"token punctuation\">.</span>meta<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_APP_WEBSITE_URL</span> <span class=\"token operator\">||</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">http://localhost:</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>websitePort<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> websiteUrl<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> SuperTokensConfig <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">appInfo</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token literal-property property\">appName</span><span class=\"token operator\">:</span> <span class=\"token string\">\"SuperTokens Demo App\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">apiDomain</span><span class=\"token operator\">:</span> <span class=\"token function\">getApiDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">websiteDomain</span><span class=\"token operator\">:</span> <span class=\"token function\">getWebsiteDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token comment\">// recipeList contains all the modules that you want to</span>\n    <span class=\"token comment\">// use from SuperTokens. See the full list here: https://supertokens.com/docs/guides</span>\n    <span class=\"token literal-property property\">recipeList</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n        EmailPassword<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        WebAuthn<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        Session<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">getRedirectionURL</span><span class=\"token operator\">:</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">context</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">.</span>action <span class=\"token operator\">===</span> <span class=\"token string\">\"SUCCESS\"</span> <span class=\"token operator\">&amp;&amp;</span> context<span class=\"token punctuation\">.</span>newSessionCreated<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            <span class=\"token keyword\">return</span> <span class=\"token string\">\"/dashboard\"</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> recipeDetails <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">docsLink</span><span class=\"token operator\">:</span> <span class=\"token string\">\"https://supertokens.com/docs/emailpassword/introduction\"</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> PreBuiltUIList <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n    EmailPasswordPreBuiltUI<span class=\"token punctuation\">,</span>\n    WebauthnPreBuiltUI<span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> ComponentWrapper <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>props<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">children</span><span class=\"token operator\">:</span> <span class=\"token constant\">JSX</span><span class=\"token punctuation\">.</span>Element <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> <span class=\"token constant\">JSX</span><span class=\"token punctuation\">.</span><span class=\"token parameter\">Element</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> props<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Now we’ll update the backend. Find the <code class=\"language-text\">config.ts</code> file located in <code class=\"language-text\">/backend/config.ts</code>, and Import WebAuthn from the recipe</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"5682777235593717000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`\nimport EmailPassword from &quot;supertokens-node/recipe/emailpassword&quot;;\nimport Session from &quot;supertokens-node/recipe/session&quot;;\nimport { TypeInput } from &quot;supertokens-node/types&quot;;\nimport Dashboard from &quot;supertokens-node/recipe/dashboard&quot;;\nimport UserRoles from &quot;supertokens-node/recipe/userroles&quot;;\n\nimport WebAuthn from &quot;supertokens-node/recipe/webauthn&quot;; // enables passkeys\n\n\nexport function getApiDomain() {\n    const apiPort = process.env.VITE_APP_API_PORT || 3001;\n    const apiUrl = process.env.VITE_APP_API_URL || \\`http://localhost:\\${apiPort}\\`;\n    return apiUrl;\n}\n\nexport function getWebsiteDomain() {\n    const websitePort = process.env.VITE_APP_WEBSITE_PORT || 3000;\n    const websiteUrl = process.env.VITE_APP_WEBSITE_URL || \\`http://localhost:\\${websitePort}\\`;\n    return websiteUrl;\n}\n\nexport const SuperTokensConfig: TypeInput = {\n    framework: &quot;koa&quot;,\n    supertokens: {\n        // this is the location of the SuperTokens core.\n        connectionURI: &quot;https://try.supertokens.com&quot;,\n    },\n    appInfo: {\n        // learn more about this on https://supertokens.com/docs/thirdpartyemailpassword/appinfo\n        appName: &quot;SuperTokens Koa demo app&quot;,\n        apiDomain: getApiDomain(),\n        websiteDomain: getWebsiteDomain(),\n    },\n    recipeList: [\n        EmailPassword.init(),\n        WebAuthn.init(),\n        Session.init(), \n        Dashboard.init(), \n        UserRoles.init()\n    ],\n};`, `5682777235593717000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">\n<span class=\"token keyword\">import</span> EmailPassword <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/recipe/emailpassword\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> Session <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/recipe/session\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> TypeInput <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/types\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> Dashboard <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/recipe/dashboard\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> UserRoles <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/recipe/userroles\"</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">import</span> WebAuthn <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/recipe/webauthn\"</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// enables passkeys</span>\n\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">function</span> <span class=\"token function\">getApiDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> apiPort <span class=\"token operator\">=</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_APP_API_PORT</span> <span class=\"token operator\">||</span> <span class=\"token number\">3001</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> apiUrl <span class=\"token operator\">=</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_APP_API_URL</span> <span class=\"token operator\">||</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">http://localhost:</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>apiPort<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> apiUrl<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">function</span> <span class=\"token function\">getWebsiteDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> websitePort <span class=\"token operator\">=</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_APP_WEBSITE_PORT</span> <span class=\"token operator\">||</span> <span class=\"token number\">3000</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> websiteUrl <span class=\"token operator\">=</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_APP_WEBSITE_URL</span> <span class=\"token operator\">||</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">http://localhost:</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>websitePort<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> websiteUrl<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token literal-property property\">SuperTokensConfig</span><span class=\"token operator\">:</span> TypeInput <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">framework</span><span class=\"token operator\">:</span> <span class=\"token string\">\"koa\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">supertokens</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token comment\">// this is the location of the SuperTokens core.</span>\n        <span class=\"token literal-property property\">connectionURI</span><span class=\"token operator\">:</span> <span class=\"token string\">\"https://try.supertokens.com\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">appInfo</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token comment\">// learn more about this on https://supertokens.com/docs/thirdpartyemailpassword/appinfo</span>\n        <span class=\"token literal-property property\">appName</span><span class=\"token operator\">:</span> <span class=\"token string\">\"SuperTokens Koa demo app\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">apiDomain</span><span class=\"token operator\">:</span> <span class=\"token function\">getApiDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">websiteDomain</span><span class=\"token operator\">:</span> <span class=\"token function\">getWebsiteDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">recipeList</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n        EmailPassword<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        WebAuthn<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        Session<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> \n        Dashboard<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> \n        UserRoles<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Navigate to <a href=\"http://localhost:3000/auth\" target=\"_blank\" rel=\"nofollow\">http://localhost:3000/auth</a> you’ll see a new option to use the passkey as an auth option</p>\n<h2 id=\"enforcing-phishing-resistant-mfa-policies\" style=\"position:relative;\"><a href=\"#enforcing-phishing-resistant-mfa-policies\" aria-label=\"enforcing phishing resistant mfa policies permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Enforcing Phishing-Resistant MFA Policies</h2>\n<p>To enable mfa we’ll use the <a href=\"https://supertokens.com/docs/additional-verification/mfa/initial-setup\" target=\"_blank\" rel=\"nofollow\">MFA recipe</a> to require multi-factor authentication, currently mfa has the support for Email/SMS One-Time Password (OTP) or Time-based One-Time Password (TOTP). Just like above we’ll be adding recipes to both the front and backend config files.</p>\n<p>Frontend adding mfa config.tsx</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"25404164581753274000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`\nimport EmailPassword from &quot;supertokens-auth-react/recipe/emailpassword&quot;;\nimport { EmailPasswordPreBuiltUI } from &quot;supertokens-auth-react/recipe/emailpassword/prebuiltui&quot;;\nimport Session from &quot;supertokens-auth-react/recipe/session&quot;;\n\nimport WebAuthn from &quot;supertokens-auth-react/recipe/webauthn&quot;; // passkeys\nimport { WebauthnPreBuiltUI } from 'supertokens-auth-react/recipe/webauthn/prebuiltui'; // passkeys\n\n// mfa\nimport MultiFactorAuth from &quot;supertokens-auth-react/recipe/multifactorauth&quot;;\nimport { MultiFactorAuthPreBuiltUI } from &quot;supertokens-auth-react/recipe/multifactorauth/prebuiltui&quot;;\nimport Passwordless from &quot;supertokens-auth-react/recipe/passwordless&quot;;\nimport { PasswordlessPreBuiltUI } from &quot;supertokens-auth-react/recipe/passwordless/prebuiltui&quot;;\nimport TOTP from &quot;supertokens-auth-react/recipe/totp&quot;;\nimport { TOTPPreBuiltUI } from &quot;supertokens-auth-react/recipe/totp/prebuiltui&quot;;\n\nexport function getApiDomain() {\n    const apiPort = import.meta.env.VITE_APP_API_PORT || 3001;\n    const apiUrl = import.meta.env.VITE_APP_API_URL || \\`http://localhost:\\${apiPort}\\`;\n    return apiUrl;\n}\n\nexport function getWebsiteDomain() {\n    const websitePort = import.meta.env.VITE_APP_WEBSITE_PORT || 3000;\n    const websiteUrl = import.meta.env.VITE_APP_WEBSITE_URL || \\`http://localhost:\\${websitePort}\\`;\n    return websiteUrl;\n}\n\nexport const SuperTokensConfig = {\n    appInfo: {\n        appName: &quot;SuperTokens Demo App&quot;,\n        apiDomain: getApiDomain(),\n        websiteDomain: getWebsiteDomain(),\n    },\n    // recipeList contains all the modules that you want to\n    // use from SuperTokens. See the full list here: https://supertokens.com/docs/guides\n    recipeList: [\n        EmailPassword.init(),\n        WebAuthn.init(),\n        Passwordless.init({\n            contactMethod: &quot;EMAIL_OR_PHONE&quot;,\n        }),\n        MultiFactorAuth.init({ \n            firstFactors: [&quot;webauthn&quot;, &quot;emailpassword&quot;]\n        }),\n        TOTP.init(),\n        Session.init()\n    ],\n    getRedirectionURL: async (context) => {\n        if (context.action === &quot;SUCCESS&quot; && context.newSessionCreated) {\n            return &quot;/dashboard&quot;;\n        }\n    },\n};\n\nexport const recipeDetails = {\n    docsLink: &quot;https://supertokens.com/docs/emailpassword/introduction&quot;,\n};\n\nexport const PreBuiltUIList = [\n    EmailPasswordPreBuiltUI,\n    WebauthnPreBuiltUI,\n    PasswordlessPreBuiltUI,\n    MultiFactorAuthPreBuiltUI,\n    TOTPPreBuiltUI\n];\n\nexport const ComponentWrapper = (props: { children: JSX.Element }): JSX.Element => {\n    return props.children;\n};\n\n`, `25404164581753274000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">\n<span class=\"token keyword\">import</span> EmailPassword <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/emailpassword\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> EmailPasswordPreBuiltUI <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/emailpassword/prebuiltui\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> Session <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/session\"</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">import</span> WebAuthn <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/webauthn\"</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// passkeys</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> WebauthnPreBuiltUI <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'supertokens-auth-react/recipe/webauthn/prebuiltui'</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// passkeys</span>\n\n<span class=\"token comment\">// mfa</span>\n<span class=\"token keyword\">import</span> MultiFactorAuth <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/multifactorauth\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> MultiFactorAuthPreBuiltUI <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/multifactorauth/prebuiltui\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> Passwordless <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/passwordless\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> PasswordlessPreBuiltUI <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/passwordless/prebuiltui\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token constant\">TOTP</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/totp\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> TOTPPreBuiltUI <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/totp/prebuiltui\"</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">function</span> <span class=\"token function\">getApiDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> apiPort <span class=\"token operator\">=</span> <span class=\"token keyword\">import</span><span class=\"token punctuation\">.</span>meta<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_APP_API_PORT</span> <span class=\"token operator\">||</span> <span class=\"token number\">3001</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> apiUrl <span class=\"token operator\">=</span> <span class=\"token keyword\">import</span><span class=\"token punctuation\">.</span>meta<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_APP_API_URL</span> <span class=\"token operator\">||</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">http://localhost:</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>apiPort<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> apiUrl<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">function</span> <span class=\"token function\">getWebsiteDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> websitePort <span class=\"token operator\">=</span> <span class=\"token keyword\">import</span><span class=\"token punctuation\">.</span>meta<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_APP_WEBSITE_PORT</span> <span class=\"token operator\">||</span> <span class=\"token number\">3000</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> websiteUrl <span class=\"token operator\">=</span> <span class=\"token keyword\">import</span><span class=\"token punctuation\">.</span>meta<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_APP_WEBSITE_URL</span> <span class=\"token operator\">||</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">http://localhost:</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>websitePort<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> websiteUrl<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> SuperTokensConfig <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">appInfo</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token literal-property property\">appName</span><span class=\"token operator\">:</span> <span class=\"token string\">\"SuperTokens Demo App\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">apiDomain</span><span class=\"token operator\">:</span> <span class=\"token function\">getApiDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">websiteDomain</span><span class=\"token operator\">:</span> <span class=\"token function\">getWebsiteDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token comment\">// recipeList contains all the modules that you want to</span>\n    <span class=\"token comment\">// use from SuperTokens. See the full list here: https://supertokens.com/docs/guides</span>\n    <span class=\"token literal-property property\">recipeList</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n        EmailPassword<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        WebAuthn<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        Passwordless<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n            <span class=\"token literal-property property\">contactMethod</span><span class=\"token operator\">:</span> <span class=\"token string\">\"EMAIL_OR_PHONE\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        MultiFactorAuth<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> \n            <span class=\"token literal-property property\">firstFactors</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"webauthn\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"emailpassword\"</span><span class=\"token punctuation\">]</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token constant\">TOTP</span><span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        Session<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">getRedirectionURL</span><span class=\"token operator\">:</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">context</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">.</span>action <span class=\"token operator\">===</span> <span class=\"token string\">\"SUCCESS\"</span> <span class=\"token operator\">&amp;&amp;</span> context<span class=\"token punctuation\">.</span>newSessionCreated<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            <span class=\"token keyword\">return</span> <span class=\"token string\">\"/dashboard\"</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> recipeDetails <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">docsLink</span><span class=\"token operator\">:</span> <span class=\"token string\">\"https://supertokens.com/docs/emailpassword/introduction\"</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> PreBuiltUIList <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n    EmailPasswordPreBuiltUI<span class=\"token punctuation\">,</span>\n    WebauthnPreBuiltUI<span class=\"token punctuation\">,</span>\n    PasswordlessPreBuiltUI<span class=\"token punctuation\">,</span>\n    MultiFactorAuthPreBuiltUI<span class=\"token punctuation\">,</span>\n    TOTPPreBuiltUI\n<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> ComponentWrapper <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>props<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">children</span><span class=\"token operator\">:</span> <span class=\"token constant\">JSX</span><span class=\"token punctuation\">.</span>Element <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> <span class=\"token constant\">JSX</span><span class=\"token punctuation\">.</span><span class=\"token parameter\">Element</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> props<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n</code></pre></div>\n<p>Backend adding mfa <code class=\"language-text\">config.tsx</code></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"6986074075188631000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`import EmailPassword from &quot;supertokens-node/recipe/emailpassword&quot;;\nimport Session from &quot;supertokens-node/recipe/session&quot;;\nimport { TypeInput } from &quot;supertokens-node/types&quot;;\nimport Dashboard from &quot;supertokens-node/recipe/dashboard&quot;;\nimport UserRoles from &quot;supertokens-node/recipe/userroles&quot;;\n\nimport WebAuthn from &quot;supertokens-node/recipe/webauthn&quot;; // enables passkeys\n\n// mfa imports\nimport AccountLinking from &quot;supertokens-node/recipe/accountlinking&quot;;\nimport MultiFactorAuth from &quot;supertokens-node/recipe/multifactorauth&quot;;\nimport TOTP from &quot;supertokens-node/recipe/totp&quot;;\nimport Passwordless from &quot;supertokens-node/recipe/passwordless&quot;;\n\nexport function getApiDomain() {\n    const apiPort = process.env.VITE_APP_API_PORT || 3001;\n    const apiUrl = process.env.VITE_APP_API_URL || \\`http://localhost:\\${apiPort}\\`;\n    return apiUrl;\n}\n\nexport function getWebsiteDomain() {\n    const websitePort = process.env.VITE_APP_WEBSITE_PORT || 3000;\n    const websiteUrl = process.env.VITE_APP_WEBSITE_URL || \\`http://localhost:\\${websitePort}\\`;\n    return websiteUrl;\n}\n\nexport const SuperTokensConfig: TypeInput = {\n    framework: &quot;koa&quot;,\n    supertokens: {\n        // this is the location of the SuperTokens core.\n        connectionURI: &quot;https://try.supertokens.com&quot;,\n    },\n    appInfo: {\n        // learn more about this on https://supertokens.com/docs/thirdpartyemailpassword/appinfo\n        appName: &quot;SuperTokens Koa demo app&quot;,\n        apiDomain: getApiDomain(),\n        websiteDomain: getWebsiteDomain(),\n    },\n    recipeList: [\n        EmailPassword.init(),\n        WebAuthn.init(),\n        Passwordless.init({\n            contactMethod: &quot;EMAIL_OR_PHONE&quot;,\n            flowType: &quot;USER_INPUT_CODE_AND_MAGIC_LINK&quot;,\n        }),\n        AccountLinking.init({\n            shouldDoAutomaticAccountLinking: async (newAccountInfo: AccountInfoWithRecipeId & { recipeUserId?: RecipeUserId }, user: User | undefined, session: SessionContainerInterface | undefined, tenantId: string, userContext: UserContext) => {\n                if (session === undefined) {\n                    // we do not want to do first factor account linking by default. To enable that,\n                    // please see the automatic account linking docs in the recipe docs for your first factor.\n                    return {\n                        shouldAutomaticallyLink: false\n                    };\n                }\n                if (user === undefined || session.getUserId() === user.id) {\n                    // if it comes here, it means that a session exists, and we are trying to link the \n                    // newAccountInfo to the session user, which means it's an MFA flow, so we enable \n                    // linking here.\n                    return {\n                        shouldAutomaticallyLink: true,\n                        shouldRequireVerification: false\n                    }\n                }\n                return {\n                    shouldAutomaticallyLink: false\n                };\n            }\n        }),\n        MultiFactorAuth.init({\n            firstFactors: [&quot;webauthn&quot;, &quot;emailpassword&quot;],\n            override: {\n                functions: (oI) => ({\n                    ...oI,\n                    getMFARequirementsForAuth: () => [\n                        {\n                            oneOf: [\n                                MultiFactorAuth.FactorIds.TOTP,\n                                MultiFactorAuth.FactorIds.OTP_EMAIL,\n                                MultiFactorAuth.FactorIds.OTP_PHONE,\n                            ],\n                        },\n                    ],\n                }),\n            },\n        }),\n        TOTP.init(),\n        Session.init(), \n        Dashboard.init(), \n        UserRoles.init()\n    ],\n};\n\n`, `6986074075188631000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">import</span> EmailPassword <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/recipe/emailpassword\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> Session <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/recipe/session\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> TypeInput <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/types\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> Dashboard <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/recipe/dashboard\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> UserRoles <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/recipe/userroles\"</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">import</span> WebAuthn <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/recipe/webauthn\"</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// enables passkeys</span>\n\n<span class=\"token comment\">// mfa imports</span>\n<span class=\"token keyword\">import</span> AccountLinking <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/recipe/accountlinking\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> MultiFactorAuth <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/recipe/multifactorauth\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token constant\">TOTP</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/recipe/totp\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> Passwordless <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/recipe/passwordless\"</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">function</span> <span class=\"token function\">getApiDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> apiPort <span class=\"token operator\">=</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_APP_API_PORT</span> <span class=\"token operator\">||</span> <span class=\"token number\">3001</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> apiUrl <span class=\"token operator\">=</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_APP_API_URL</span> <span class=\"token operator\">||</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">http://localhost:</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>apiPort<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> apiUrl<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">function</span> <span class=\"token function\">getWebsiteDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> websitePort <span class=\"token operator\">=</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_APP_WEBSITE_PORT</span> <span class=\"token operator\">||</span> <span class=\"token number\">3000</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> websiteUrl <span class=\"token operator\">=</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_APP_WEBSITE_URL</span> <span class=\"token operator\">||</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">http://localhost:</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>websitePort<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> websiteUrl<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token literal-property property\">SuperTokensConfig</span><span class=\"token operator\">:</span> TypeInput <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">framework</span><span class=\"token operator\">:</span> <span class=\"token string\">\"koa\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">supertokens</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token comment\">// this is the location of the SuperTokens core.</span>\n        <span class=\"token literal-property property\">connectionURI</span><span class=\"token operator\">:</span> <span class=\"token string\">\"https://try.supertokens.com\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">appInfo</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token comment\">// learn more about this on https://supertokens.com/docs/thirdpartyemailpassword/appinfo</span>\n        <span class=\"token literal-property property\">appName</span><span class=\"token operator\">:</span> <span class=\"token string\">\"SuperTokens Koa demo app\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">apiDomain</span><span class=\"token operator\">:</span> <span class=\"token function\">getApiDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">websiteDomain</span><span class=\"token operator\">:</span> <span class=\"token function\">getWebsiteDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">recipeList</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n        EmailPassword<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        WebAuthn<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        Passwordless<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n            <span class=\"token literal-property property\">contactMethod</span><span class=\"token operator\">:</span> <span class=\"token string\">\"EMAIL_OR_PHONE\"</span><span class=\"token punctuation\">,</span>\n            <span class=\"token literal-property property\">flowType</span><span class=\"token operator\">:</span> <span class=\"token string\">\"USER_INPUT_CODE_AND_MAGIC_LINK\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        AccountLinking<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n            <span class=\"token function-variable function\">shouldDoAutomaticAccountLinking</span><span class=\"token operator\">:</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token literal-property property\">newAccountInfo</span><span class=\"token operator\">:</span> AccountInfoWithRecipeId <span class=\"token operator\">&amp;</span> <span class=\"token punctuation\">{</span> recipeUserId<span class=\"token operator\">?</span><span class=\"token operator\">:</span> RecipeUserId <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">user</span><span class=\"token operator\">:</span> User <span class=\"token operator\">|</span> <span class=\"token keyword\">undefined</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">session</span><span class=\"token operator\">:</span> SessionContainerInterface <span class=\"token operator\">|</span> <span class=\"token keyword\">undefined</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">tenantId</span><span class=\"token operator\">:</span> string<span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">userContext</span><span class=\"token operator\">:</span> UserContext</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n                <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>session <span class=\"token operator\">===</span> <span class=\"token keyword\">undefined</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n                    <span class=\"token comment\">// we do not want to do first factor account linking by default. To enable that,</span>\n                    <span class=\"token comment\">// please see the automatic account linking docs in the recipe docs for your first factor.</span>\n                    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">{</span>\n                        <span class=\"token literal-property property\">shouldAutomaticallyLink</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span>\n                    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n                <span class=\"token punctuation\">}</span>\n                <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>user <span class=\"token operator\">===</span> <span class=\"token keyword\">undefined</span> <span class=\"token operator\">||</span> session<span class=\"token punctuation\">.</span><span class=\"token function\">getUserId</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">===</span> user<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n                    <span class=\"token comment\">// if it comes here, it means that a session exists, and we are trying to link the </span>\n                    <span class=\"token comment\">// newAccountInfo to the session user, which means it's an MFA flow, so we enable </span>\n                    <span class=\"token comment\">// linking here.</span>\n                    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">{</span>\n                        <span class=\"token literal-property property\">shouldAutomaticallyLink</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n                        <span class=\"token literal-property property\">shouldRequireVerification</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span>\n                    <span class=\"token punctuation\">}</span>\n                <span class=\"token punctuation\">}</span>\n                <span class=\"token keyword\">return</span> <span class=\"token punctuation\">{</span>\n                    <span class=\"token literal-property property\">shouldAutomaticallyLink</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span>\n                <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n            <span class=\"token punctuation\">}</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        MultiFactorAuth<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n            <span class=\"token literal-property property\">firstFactors</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"webauthn\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"emailpassword\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n            <span class=\"token literal-property property\">override</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n                <span class=\"token function-variable function\">functions</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">oI</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n                    <span class=\"token operator\">...</span>oI<span class=\"token punctuation\">,</span>\n                    <span class=\"token function-variable function\">getMFARequirementsForAuth</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">[</span>\n                        <span class=\"token punctuation\">{</span>\n                            <span class=\"token literal-property property\">oneOf</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n                                MultiFactorAuth<span class=\"token punctuation\">.</span>FactorIds<span class=\"token punctuation\">.</span><span class=\"token constant\">TOTP</span><span class=\"token punctuation\">,</span>\n                                MultiFactorAuth<span class=\"token punctuation\">.</span>FactorIds<span class=\"token punctuation\">.</span><span class=\"token constant\">OTP_EMAIL</span><span class=\"token punctuation\">,</span>\n                                MultiFactorAuth<span class=\"token punctuation\">.</span>FactorIds<span class=\"token punctuation\">.</span><span class=\"token constant\">OTP_PHONE</span><span class=\"token punctuation\">,</span>\n                            <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n            <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token constant\">TOTP</span><span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        Session<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> \n        Dashboard<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> \n        UserRoles<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n</code></pre></div>\n<h2 id=\"testing-your-mfa-implementation\" style=\"position:relative;\"><a href=\"#testing-your-mfa-implementation\" aria-label=\"testing your mfa implementation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Testing Your MFA Implementation</h2>\n<h3 id=\"unit-tests\" style=\"position:relative;\"><a href=\"#unit-tests\" aria-label=\"unit tests permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Unit Tests</h3>\n<p>Let’s add some unit tests to test the flow - Sign up, Session verification, Refreshing session tokens, and Logout. Create a test directory in the backend <code class=\"language-text\">/backend/__tests__</code></p>\n<p>Backend <code class=\"language-text\">auth-flow.test.ts</code></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"19589297603779408000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`\nimport SuperTokens from 'supertokens-node';\nimport EmailPassword from 'supertokens-node/recipe/emailpassword';\nimport Session from 'supertokens-node/recipe/session';\nimport { SessionContainerInterface } from 'supertokens-node/recipe/session/types';\nimport { User } from 'supertokens-node/types';\n\n// Mock dependencies\njest.mock('supertokens-node', () => ({\n  init: jest.fn(),\n}));\n\njest.mock('supertokens-node/recipe/emailpassword', () => ({\n  signUp: jest.fn(),\n  signIn: jest.fn(),\n}));\n\njest.mock('supertokens-node/recipe/session', () => ({\n  createNewSession: jest.fn(),\n  getSession: jest.fn(),\n  revokeAllSessionsForUser: jest.fn(),\n}));\n\ndescribe('Authentication Flow Tests', () => {\n  // Comprehensive mock user data\n  const mockUser: User = {\n    id: 'test_st',\n    emails: ['test@example.com'],\n    timeJoined: Date.now(),\n    isPrimaryUser: true,\n    tenantIds: ['default'],\n    phoneNumbers: [],\n    thirdParty: null,\n    loginMethods: [],\n    webauthn: {\n      credentialIds: ['mock-credential-id'],\n    },\n    toJson: () => ({\n      id: 'test_st',\n      emails: ['test@example.com'],\n    }),\n  };\n\n  // Mock session container\n  const createMockSessionContainer = (userId: string): SessionContainerInterface => ({\n    revokeSession: jest.fn(),\n    getSessionDataFromDatabase: jest.fn(),\n    updateSessionDataInDatabase: jest.fn(),\n    getUserId: () => userId,\n    getAccessToken: () => 'mock-access-token',\n    getHandle: () => 'mock-session-handle',\n    getRecipeUserId: jest.fn().mockReturnValue({ getAsString: () => userId }),\n    getTenantId: jest.fn().mockReturnValue('default'),\n    getAccessTokenPayload: jest.fn().mockReturnValue({}),\n    getAllSessionTokensDangerously: jest.fn().mockReturnValue({\n      accessToken: 'mock-access-token',\n      refreshToken: 'mock-refresh-token',\n    }),\n    mergeIntoAccessTokenPayload: jest.fn(),\n    getTimeCreated: jest.fn().mockReturnValue(Date.now()),\n    getExpiry: jest.fn().mockReturnValue(Date.now() + 3600000),\n    assertClaims: jest.fn(),\n    \n    // Adding missing methods with mock implementations\n    fetchAndSetClaim: jest.fn(),\n    setClaimValue: jest.fn(),\n    getClaimValue: jest.fn(),\n    removeClaim: jest.fn(),\n    attachToRequestResponse: jest.fn(),\n  });\n\n  // Reset all mocks before each test\n  beforeEach(() => {\n    jest.clearAllMocks();\n  });\n\n  // Utility function to create sign up/in response\n  const createSuccessResponse = () => ({\n    status: &quot;OK&quot; as const,\n    user: mockUser,\n    recipeUserId: {\n      getAsString: () => mockUser.id,\n    },\n  });\n\n  // Test 1: Sign Up\n  test('should successfully sign up a new user', async () => {\n    // Arrange\n    const mockSignUpResponse = createSuccessResponse();\n    const mockAlreadyExistsResponse = { \n      status: &quot;EMAIL_ALREADY_EXISTS_ERROR&quot; as const \n    };\n\n    (EmailPassword.signUp as jest.Mock)\n      .mockImplementation((tenantId, email, password) => {\n        if (email === 'test@example.com') {\n          return Promise.resolve(mockSignUpResponse);\n        }\n        if (email === 'existing@example.com') {\n          return Promise.resolve(mockAlreadyExistsResponse);\n        }\n        throw new Error('Unexpected email');\n      });\n\n    const mockSession = createMockSessionContainer(mockUser.id);\n    (Session.createNewSession as jest.Mock).mockResolvedValue(mockSession);\n\n    // Act\n    const signUpResult = await EmailPassword.signUp(\n      'tenant-id', \n      'test@example.com', \n      'Test123!'\n    );\n\n    // Assert\n    expect(signUpResult).toEqual(expect.objectContaining({\n      status: &quot;OK&quot;,\n      user: expect.objectContaining({\n        emails: expect.arrayContaining(['test@example.com'])\n      })\n    }));\n\n    // Try signing up with existing email\n    const existingEmailResult = await EmailPassword.signUp(\n      'tenant-id', \n      'existing@example.com', \n      'Test123!'\n    );\n\n    expect(existingEmailResult).toEqual({\n      status: &quot;EMAIL_ALREADY_EXISTS_ERROR&quot;\n    });\n  });\n\n  // Test 2: Session Verification\n  test('should get user session', async () => {\n    // Arrange\n    const mockSession = createMockSessionContainer(mockUser.id);\n\n    (Session.getSession as jest.Mock).mockResolvedValue(mockSession);\n\n    // Act\n    const sessionResult = await Session.getSession(\n      {} as any,  // req\n      {} as any,  // res\n      {}  // options\n    );\n\n    // Assert\n    expect(sessionResult.getUserId()).toBe(mockUser.id);\n    expect(Session.getSession).toHaveBeenCalled();\n  });\n\n  // Test 3: Revoking Sessions\n  test('should revoke all sessions for a user', async () => {\n    // Arrange\n    const mockRevokeResponse: string[] = [mockUser.id];\n\n    (Session.revokeAllSessionsForUser as jest.Mock).mockResolvedValue(mockRevokeResponse);\n\n    // Act\n    const revokeResult = await Session.revokeAllSessionsForUser(mockUser.id);\n\n    // Assert\n    expect(revokeResult).toEqual([mockUser.id]);\n    expect(Session.revokeAllSessionsForUser).toHaveBeenCalledWith(mockUser.id);\n  });\n\n  // Test 4: Sign In\n  test('should successfully sign in an existing user', async () => {\n    // Arrange\n    const mockSignInResponse = createSuccessResponse();\n    const mockWrongCredentialsResponse = { \n      status: &quot;WRONG_CREDENTIALS_ERROR&quot; as const \n    };\n\n    (EmailPassword.signIn as jest.Mock)\n      .mockImplementation((tenantId, email, password) => {\n        if (email === 'test@example.com') {\n          return Promise.resolve(mockSignInResponse);\n        }\n        if (email === 'wrong@example.com') {\n          return Promise.resolve(mockWrongCredentialsResponse);\n        }\n        throw new Error('Unexpected email');\n      });\n\n    const mockSession = createMockSessionContainer(mockUser.id);\n    (Session.createNewSession as jest.Mock).mockResolvedValue(mockSession);\n\n    // Act\n    const signInResult = await EmailPassword.signIn(\n      'tenant-id', \n      'test@example.com', \n      'Test123!'\n    );\n\n    // Assert\n    expect(signInResult).toEqual(expect.objectContaining({\n      status: &quot;OK&quot;,\n      user: expect.objectContaining({\n        emails: expect.arrayContaining(['test@example.com'])\n      })\n    }));\n\n    // Try signing in with wrong credentials\n    const wrongCredentialsResult = await EmailPassword.signIn(\n      'tenant-id', \n      'wrong@example.com', \n      'WrongPass123!'\n    );\n\n    expect(wrongCredentialsResult).toEqual({\n      status: &quot;WRONG_CREDENTIALS_ERROR&quot;\n    });\n  });\n\n  // Error Handling Tests\n  describe('Error Scenarios', () => {\n    test('should handle sign up failure', async () => {\n      // Arrange\n      const mockError = new Error('Sign up failed');\n      \n      (EmailPassword.signUp as jest.Mock).mockRejectedValue(mockError);\n\n      // Act & Assert\n      await expect(EmailPassword.signUp(\n        'tenant-id',\n        'test@example.com', \n        'Test123!'\n      )).rejects.toThrow('Sign up failed');\n    });\n\n    test('should handle session retrieval failure', async () => {\n      // Arrange\n      const mockError = new Error('Invalid session');\n      \n      (Session.getSession as jest.Mock).mockRejectedValue(mockError);\n\n      // Act & Assert\n      await expect(Session.getSession(\n        {} as any,  // req\n        {} as any,  // res\n        {}  // options\n      )).rejects.toThrow('Invalid session');\n    });\n  });\n});`, `19589297603779408000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">\n<span class=\"token keyword\">import</span> SuperTokens <span class=\"token keyword\">from</span> <span class=\"token string\">'supertokens-node'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> EmailPassword <span class=\"token keyword\">from</span> <span class=\"token string\">'supertokens-node/recipe/emailpassword'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> Session <span class=\"token keyword\">from</span> <span class=\"token string\">'supertokens-node/recipe/session'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> SessionContainerInterface <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'supertokens-node/recipe/session/types'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> User <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'supertokens-node/types'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Mock dependencies</span>\njest<span class=\"token punctuation\">.</span><span class=\"token function\">mock</span><span class=\"token punctuation\">(</span><span class=\"token string\">'supertokens-node'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">init</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\njest<span class=\"token punctuation\">.</span><span class=\"token function\">mock</span><span class=\"token punctuation\">(</span><span class=\"token string\">'supertokens-node/recipe/emailpassword'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">signUp</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">signIn</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\njest<span class=\"token punctuation\">.</span><span class=\"token function\">mock</span><span class=\"token punctuation\">(</span><span class=\"token string\">'supertokens-node/recipe/session'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">createNewSession</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">getSession</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">revokeAllSessionsForUser</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Authentication Flow Tests'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// Comprehensive mock user data</span>\n  <span class=\"token keyword\">const</span> <span class=\"token literal-property property\">mockUser</span><span class=\"token operator\">:</span> User <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">id</span><span class=\"token operator\">:</span> <span class=\"token string\">'test_st'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">emails</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'test@example.com'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">timeJoined</span><span class=\"token operator\">:</span> Date<span class=\"token punctuation\">.</span><span class=\"token function\">now</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">isPrimaryUser</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">tenantIds</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'default'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">phoneNumbers</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">thirdParty</span><span class=\"token operator\">:</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">loginMethods</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">webauthn</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token literal-property property\">credentialIds</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'mock-credential-id'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">toJson</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n      <span class=\"token literal-property property\">id</span><span class=\"token operator\">:</span> <span class=\"token string\">'test_st'</span><span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">emails</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'test@example.com'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Mock session container</span>\n  <span class=\"token keyword\">const</span> createMockSessionContainer <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>userId<span class=\"token operator\">:</span> string<span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> <span class=\"token parameter\">SessionContainerInterface</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">revokeSession</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">getSessionDataFromDatabase</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">updateSessionDataInDatabase</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">getUserId</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> userId<span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">getAccessToken</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token string\">'mock-access-token'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">getHandle</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token string\">'mock-session-handle'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">getRecipeUserId</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">mockReturnValue</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token function-variable function\">getAsString</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> userId <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">getTenantId</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">mockReturnValue</span><span class=\"token punctuation\">(</span><span class=\"token string\">'default'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">getAccessTokenPayload</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">mockReturnValue</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">getAllSessionTokensDangerously</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">mockReturnValue</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n      <span class=\"token literal-property property\">accessToken</span><span class=\"token operator\">:</span> <span class=\"token string\">'mock-access-token'</span><span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">refreshToken</span><span class=\"token operator\">:</span> <span class=\"token string\">'mock-refresh-token'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">mergeIntoAccessTokenPayload</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">getTimeCreated</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">mockReturnValue</span><span class=\"token punctuation\">(</span>Date<span class=\"token punctuation\">.</span><span class=\"token function\">now</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">getExpiry</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">mockReturnValue</span><span class=\"token punctuation\">(</span>Date<span class=\"token punctuation\">.</span><span class=\"token function\">now</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">+</span> <span class=\"token number\">3600000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">assertClaims</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    \n    <span class=\"token comment\">// Adding missing methods with mock implementations</span>\n    <span class=\"token literal-property property\">fetchAndSetClaim</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">setClaimValue</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">getClaimValue</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">removeClaim</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">attachToRequestResponse</span><span class=\"token operator\">:</span> jest<span class=\"token punctuation\">.</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Reset all mocks before each test</span>\n  <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    jest<span class=\"token punctuation\">.</span><span class=\"token function\">clearAllMocks</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Utility function to create sign up/in response</span>\n  <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">createSuccessResponse</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">status</span><span class=\"token operator\">:</span> <span class=\"token string\">\"OK\"</span> <span class=\"token keyword\">as</span> <span class=\"token keyword\">const</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">user</span><span class=\"token operator\">:</span> mockUser<span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">recipeUserId</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token function-variable function\">getAsString</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> mockUser<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Test 1: Sign Up</span>\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'should successfully sign up a new user'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Arrange</span>\n    <span class=\"token keyword\">const</span> mockSignUpResponse <span class=\"token operator\">=</span> <span class=\"token function\">createSuccessResponse</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> mockAlreadyExistsResponse <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> \n      <span class=\"token literal-property property\">status</span><span class=\"token operator\">:</span> <span class=\"token string\">\"EMAIL_ALREADY_EXISTS_ERROR\"</span> <span class=\"token keyword\">as</span> <span class=\"token keyword\">const</span> \n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token punctuation\">(</span>EmailPassword<span class=\"token punctuation\">.</span>signUp <span class=\"token keyword\">as</span> jest<span class=\"token punctuation\">.</span>Mock<span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">.</span><span class=\"token function\">mockImplementation</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">tenantId<span class=\"token punctuation\">,</span> email<span class=\"token punctuation\">,</span> password</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>email <span class=\"token operator\">===</span> <span class=\"token string\">'test@example.com'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n          <span class=\"token keyword\">return</span> Promise<span class=\"token punctuation\">.</span><span class=\"token function\">resolve</span><span class=\"token punctuation\">(</span>mockSignUpResponse<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>email <span class=\"token operator\">===</span> <span class=\"token string\">'existing@example.com'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n          <span class=\"token keyword\">return</span> Promise<span class=\"token punctuation\">.</span><span class=\"token function\">resolve</span><span class=\"token punctuation\">(</span>mockAlreadyExistsResponse<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n        <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Unexpected email'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">const</span> mockSession <span class=\"token operator\">=</span> <span class=\"token function\">createMockSessionContainer</span><span class=\"token punctuation\">(</span>mockUser<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">(</span>Session<span class=\"token punctuation\">.</span>createNewSession <span class=\"token keyword\">as</span> jest<span class=\"token punctuation\">.</span>Mock<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">mockResolvedValue</span><span class=\"token punctuation\">(</span>mockSession<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Act</span>\n    <span class=\"token keyword\">const</span> signUpResult <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> EmailPassword<span class=\"token punctuation\">.</span><span class=\"token function\">signUp</span><span class=\"token punctuation\">(</span>\n      <span class=\"token string\">'tenant-id'</span><span class=\"token punctuation\">,</span> \n      <span class=\"token string\">'test@example.com'</span><span class=\"token punctuation\">,</span> \n      <span class=\"token string\">'Test123!'</span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Assert</span>\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>signUpResult<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toEqual</span><span class=\"token punctuation\">(</span>expect<span class=\"token punctuation\">.</span><span class=\"token function\">objectContaining</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n      <span class=\"token literal-property property\">status</span><span class=\"token operator\">:</span> <span class=\"token string\">\"OK\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">user</span><span class=\"token operator\">:</span> expect<span class=\"token punctuation\">.</span><span class=\"token function\">objectContaining</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n        <span class=\"token literal-property property\">emails</span><span class=\"token operator\">:</span> expect<span class=\"token punctuation\">.</span><span class=\"token function\">arrayContaining</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">'test@example.com'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Try signing up with existing email</span>\n    <span class=\"token keyword\">const</span> existingEmailResult <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> EmailPassword<span class=\"token punctuation\">.</span><span class=\"token function\">signUp</span><span class=\"token punctuation\">(</span>\n      <span class=\"token string\">'tenant-id'</span><span class=\"token punctuation\">,</span> \n      <span class=\"token string\">'existing@example.com'</span><span class=\"token punctuation\">,</span> \n      <span class=\"token string\">'Test123!'</span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>existingEmailResult<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toEqual</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n      <span class=\"token literal-property property\">status</span><span class=\"token operator\">:</span> <span class=\"token string\">\"EMAIL_ALREADY_EXISTS_ERROR\"</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Test 2: Session Verification</span>\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'should get user session'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Arrange</span>\n    <span class=\"token keyword\">const</span> mockSession <span class=\"token operator\">=</span> <span class=\"token function\">createMockSessionContainer</span><span class=\"token punctuation\">(</span>mockUser<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token punctuation\">(</span>Session<span class=\"token punctuation\">.</span>getSession <span class=\"token keyword\">as</span> jest<span class=\"token punctuation\">.</span>Mock<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">mockResolvedValue</span><span class=\"token punctuation\">(</span>mockSession<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Act</span>\n    <span class=\"token keyword\">const</span> sessionResult <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> Session<span class=\"token punctuation\">.</span><span class=\"token function\">getSession</span><span class=\"token punctuation\">(</span>\n      <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span> <span class=\"token keyword\">as</span> any<span class=\"token punctuation\">,</span>  <span class=\"token comment\">// req</span>\n      <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span> <span class=\"token keyword\">as</span> any<span class=\"token punctuation\">,</span>  <span class=\"token comment\">// res</span>\n      <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span>  <span class=\"token comment\">// options</span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Assert</span>\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>sessionResult<span class=\"token punctuation\">.</span><span class=\"token function\">getUserId</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBe</span><span class=\"token punctuation\">(</span>mockUser<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>Session<span class=\"token punctuation\">.</span>getSession<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toHaveBeenCalled</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Test 3: Revoking Sessions</span>\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'should revoke all sessions for a user'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Arrange</span>\n    <span class=\"token keyword\">const</span> <span class=\"token literal-property property\">mockRevokeResponse</span><span class=\"token operator\">:</span> string<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>mockUser<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token punctuation\">(</span>Session<span class=\"token punctuation\">.</span>revokeAllSessionsForUser <span class=\"token keyword\">as</span> jest<span class=\"token punctuation\">.</span>Mock<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">mockResolvedValue</span><span class=\"token punctuation\">(</span>mockRevokeResponse<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Act</span>\n    <span class=\"token keyword\">const</span> revokeResult <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> Session<span class=\"token punctuation\">.</span><span class=\"token function\">revokeAllSessionsForUser</span><span class=\"token punctuation\">(</span>mockUser<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Assert</span>\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>revokeResult<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toEqual</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span>mockUser<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>Session<span class=\"token punctuation\">.</span>revokeAllSessionsForUser<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toHaveBeenCalledWith</span><span class=\"token punctuation\">(</span>mockUser<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Test 4: Sign In</span>\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'should successfully sign in an existing user'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Arrange</span>\n    <span class=\"token keyword\">const</span> mockSignInResponse <span class=\"token operator\">=</span> <span class=\"token function\">createSuccessResponse</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> mockWrongCredentialsResponse <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> \n      <span class=\"token literal-property property\">status</span><span class=\"token operator\">:</span> <span class=\"token string\">\"WRONG_CREDENTIALS_ERROR\"</span> <span class=\"token keyword\">as</span> <span class=\"token keyword\">const</span> \n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token punctuation\">(</span>EmailPassword<span class=\"token punctuation\">.</span>signIn <span class=\"token keyword\">as</span> jest<span class=\"token punctuation\">.</span>Mock<span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">.</span><span class=\"token function\">mockImplementation</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">tenantId<span class=\"token punctuation\">,</span> email<span class=\"token punctuation\">,</span> password</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>email <span class=\"token operator\">===</span> <span class=\"token string\">'test@example.com'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n          <span class=\"token keyword\">return</span> Promise<span class=\"token punctuation\">.</span><span class=\"token function\">resolve</span><span class=\"token punctuation\">(</span>mockSignInResponse<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>email <span class=\"token operator\">===</span> <span class=\"token string\">'wrong@example.com'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n          <span class=\"token keyword\">return</span> Promise<span class=\"token punctuation\">.</span><span class=\"token function\">resolve</span><span class=\"token punctuation\">(</span>mockWrongCredentialsResponse<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n        <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Unexpected email'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">const</span> mockSession <span class=\"token operator\">=</span> <span class=\"token function\">createMockSessionContainer</span><span class=\"token punctuation\">(</span>mockUser<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">(</span>Session<span class=\"token punctuation\">.</span>createNewSession <span class=\"token keyword\">as</span> jest<span class=\"token punctuation\">.</span>Mock<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">mockResolvedValue</span><span class=\"token punctuation\">(</span>mockSession<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Act</span>\n    <span class=\"token keyword\">const</span> signInResult <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> EmailPassword<span class=\"token punctuation\">.</span><span class=\"token function\">signIn</span><span class=\"token punctuation\">(</span>\n      <span class=\"token string\">'tenant-id'</span><span class=\"token punctuation\">,</span> \n      <span class=\"token string\">'test@example.com'</span><span class=\"token punctuation\">,</span> \n      <span class=\"token string\">'Test123!'</span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Assert</span>\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>signInResult<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toEqual</span><span class=\"token punctuation\">(</span>expect<span class=\"token punctuation\">.</span><span class=\"token function\">objectContaining</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n      <span class=\"token literal-property property\">status</span><span class=\"token operator\">:</span> <span class=\"token string\">\"OK\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">user</span><span class=\"token operator\">:</span> expect<span class=\"token punctuation\">.</span><span class=\"token function\">objectContaining</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n        <span class=\"token literal-property property\">emails</span><span class=\"token operator\">:</span> expect<span class=\"token punctuation\">.</span><span class=\"token function\">arrayContaining</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">'test@example.com'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Try signing in with wrong credentials</span>\n    <span class=\"token keyword\">const</span> wrongCredentialsResult <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> EmailPassword<span class=\"token punctuation\">.</span><span class=\"token function\">signIn</span><span class=\"token punctuation\">(</span>\n      <span class=\"token string\">'tenant-id'</span><span class=\"token punctuation\">,</span> \n      <span class=\"token string\">'wrong@example.com'</span><span class=\"token punctuation\">,</span> \n      <span class=\"token string\">'WrongPass123!'</span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>wrongCredentialsResult<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toEqual</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n      <span class=\"token literal-property property\">status</span><span class=\"token operator\">:</span> <span class=\"token string\">\"WRONG_CREDENTIALS_ERROR\"</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Error Handling Tests</span>\n  <span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Error Scenarios'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'should handle sign up failure'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">// Arrange</span>\n      <span class=\"token keyword\">const</span> mockError <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Sign up failed'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      \n      <span class=\"token punctuation\">(</span>EmailPassword<span class=\"token punctuation\">.</span>signUp <span class=\"token keyword\">as</span> jest<span class=\"token punctuation\">.</span>Mock<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">mockRejectedValue</span><span class=\"token punctuation\">(</span>mockError<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n      <span class=\"token comment\">// Act &amp; Assert</span>\n      <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>EmailPassword<span class=\"token punctuation\">.</span><span class=\"token function\">signUp</span><span class=\"token punctuation\">(</span>\n        <span class=\"token string\">'tenant-id'</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string\">'test@example.com'</span><span class=\"token punctuation\">,</span> \n        <span class=\"token string\">'Test123!'</span>\n      <span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>rejects<span class=\"token punctuation\">.</span><span class=\"token function\">toThrow</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Sign up failed'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'should handle session retrieval failure'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">// Arrange</span>\n      <span class=\"token keyword\">const</span> mockError <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Invalid session'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      \n      <span class=\"token punctuation\">(</span>Session<span class=\"token punctuation\">.</span>getSession <span class=\"token keyword\">as</span> jest<span class=\"token punctuation\">.</span>Mock<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">mockRejectedValue</span><span class=\"token punctuation\">(</span>mockError<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n      <span class=\"token comment\">// Act &amp; Assert</span>\n      <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>Session<span class=\"token punctuation\">.</span><span class=\"token function\">getSession</span><span class=\"token punctuation\">(</span>\n        <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span> <span class=\"token keyword\">as</span> any<span class=\"token punctuation\">,</span>  <span class=\"token comment\">// req</span>\n        <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span> <span class=\"token keyword\">as</span> any<span class=\"token punctuation\">,</span>  <span class=\"token comment\">// res</span>\n        <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span>  <span class=\"token comment\">// options</span>\n      <span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>rejects<span class=\"token punctuation\">.</span><span class=\"token function\">toThrow</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Invalid session'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Updates also need to be made to the <code class=\"language-text\">package.json</code> to include our test packages and to add the cmd <code class=\"language-text\">npm test</code></p>\n<p><code class=\"language-text\">package.json</code></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"92402825471323550000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`\n{\n    &quot;scripts&quot;: {\n        &quot;start&quot;: &quot;npx vite-node ./main.ts&quot;,\n        &quot;lint&quot;: &quot;eslint .&quot;,\n        &quot;build&quot;: &quot;tsc&quot;,\n        &quot;test&quot;: &quot;jest&quot;\n    },\n    &quot;dependencies&quot;: {\n        &quot;@koa/cors&quot;: &quot;^5.0.0&quot;,\n        &quot;koa&quot;: &quot;^2.15.3&quot;,\n        &quot;koa-router&quot;: &quot;^12.0.0&quot;,\n        &quot;supertokens-node&quot;: &quot;latest&quot;,\n        &quot;typescript&quot;: &quot;^4.7.2&quot;\n    },\n    &quot;devDependencies&quot;: {\n        &quot;@eslint/js&quot;: &quot;^9.17.0&quot;,\n        &quot;@types/jest&quot;: &quot;^29.5.11&quot;,\n        &quot;@types/koa__cors&quot;: &quot;^4.0.0&quot;,\n        &quot;@types/koa-router&quot;: &quot;^7.4.4&quot;,\n        &quot;@types/node&quot;: &quot;^20.11.0&quot;,\n        &quot;@types/node-fetch&quot;: &quot;^2.6.11&quot;,\n        &quot;axios&quot;: &quot;^1.6.2&quot;,\n        &quot;eslint&quot;: &quot;^9.17.0&quot;,\n        &quot;globals&quot;: &quot;^15.13.0&quot;,\n        &quot;jest&quot;: &quot;^29.7.0&quot;,\n        &quot;node-fetch&quot;: &quot;^2.7.0&quot;,\n        &quot;qs&quot;: &quot;^6.11.2&quot;,\n        &quot;ts-jest&quot;: &quot;^29.1.1&quot;,\n        &quot;typescript-eslint&quot;: &quot;^8.18.1&quot;,\n        &quot;vite-node&quot;: &quot;^2.1.8&quot;,\n        &quot;jest-mock&quot;: &quot;^29.7.0&quot;,\n        &quot;@types/jest&quot;: &quot;^29.5.11&quot;\n    }\n}\n\n`, `92402825471323550000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">\n<span class=\"token punctuation\">{</span>\n    <span class=\"token string-property property\">\"scripts\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token string-property property\">\"start\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"npx vite-node ./main.ts\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"lint\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"eslint .\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"build\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"tsc\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"test\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"jest\"</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string-property property\">\"dependencies\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token string-property property\">\"@koa/cors\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^5.0.0\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"koa\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^2.15.3\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"koa-router\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^12.0.0\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"supertokens-node\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"latest\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"typescript\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^4.7.2\"</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string-property property\">\"devDependencies\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token string-property property\">\"@eslint/js\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^9.17.0\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"@types/jest\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^29.5.11\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"@types/koa__cors\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^4.0.0\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"@types/koa-router\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^7.4.4\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"@types/node\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^20.11.0\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"@types/node-fetch\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^2.6.11\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"axios\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^1.6.2\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"eslint\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^9.17.0\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"globals\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^15.13.0\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"jest\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^29.7.0\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"node-fetch\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^2.7.0\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"qs\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^6.11.2\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"ts-jest\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^29.1.1\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"typescript-eslint\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^8.18.1\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"vite-node\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^2.1.8\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"jest-mock\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^29.7.0\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-property property\">\"@types/jest\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"^29.5.11\"</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n</code></pre></div>\n<p>Run <code class=\"language-text\">npm install</code> then <code class=\"language-text\">npm test</code></p>\n<p>It’s worth noting the unit tests we added are mocking the api calls. In an enterprise environment ideally there would also be a staging/canary environment that allows full live end-to-end testing for the service.</p>\n<h3 id=\"logging-and-metrics\" style=\"position:relative;\"><a href=\"#logging-and-metrics\" aria-label=\"logging and metrics permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Logging and Metrics</h3>\n<p>Logging and Metrics are two important aspects every service should have. They help provide a clear picture into your system to better scale infra or track down a loose bug.</p>\n<p>Looking at <code class=\"language-text\">/backend/main.ts</code> we’ll track how many times a user has logged in, maybe this can provide an insight into strange user behavior to keep an eye out for:</p>\n<p>Backend <code class=\"language-text\">main.ts</code></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"40567668967029570000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`\nimport Koa from &quot;koa&quot;;\nimport cors from &quot;@koa/cors&quot;;\nimport supertokens from &quot;supertokens-node&quot;;\nimport { middleware } from &quot;supertokens-node/framework/koa&quot;;\nimport { getWebsiteDomain, SuperTokensConfig } from &quot;./config&quot;;\nimport KoaRouter from &quot;koa-router&quot;;\nimport { verifySession } from &quot;supertokens-node/recipe/session/framework/koa&quot;;\nimport { SessionContext } from &quot;supertokens-node/framework/koa&quot;;\nimport Multitenancy from &quot;supertokens-node/recipe/multitenancy&quot;;\n\nimport { deleteUser } from &quot;supertokens-node&quot;;\n\n// basic structures to hold our metrics\ninterface AuthAttempt {\n    time: string;\n    userId: string;\n    status: string;\n}\n\nconst authLogs = {\n    success: 0,\n    recentAttempts: [] as AuthAttempt[]\n};\n\nsupertokens.init(SuperTokensConfig);\n\nconst app = new Koa();\n\nconst router = new KoaRouter();\n\napp.use(\n    cors({\n        origin: getWebsiteDomain(),\n        allowHeaders: [&quot;content-type&quot;, ...supertokens.getAllCORSHeaders()],\n        credentials: true,\n    })\n);\n\n// This exposes all the APIs from SuperTokens to the client.\napp.use(middleware());\n\n// This endpoint can be accessed regardless of\n// having a session with SuperTokens\nrouter.get(&quot;/hello&quot;, (ctx: SessionContext) => {\n    ctx.body = &quot;hello&quot;;\n});\n\n// An example API that requires session verification\nrouter.get(&quot;/sessioninfo&quot;, verifySession(), (ctx: SessionContext) => {\n    const userId = ctx.session!.getUserId();\n    \n    // Log successful authentication\n    authLogs.success++;\n    authLogs.recentAttempts.push({\n        time: new Date().toISOString(),\n        userId,\n        status: &quot;success&quot;\n    });\n    \n    ctx.status = 200;\n    ctx.body = {\n        userId,\n        status: &quot;ok&quot;,\n        authStats: authLogs\n    };\n});\n\n// This API is used by the frontend to create the tenants drop down when the app loads.\n// Depending on your UX, you can remove this API.\nrouter.get(&quot;/tenants&quot;, async (ctx: SessionContext) => {\n    const tenants = await Multitenancy.listAllTenants();\n    ctx.body = JSON.stringify({ tenants }, null, 4);\n});\n\napp.use(router.routes());\n\nif (!module.parent) app.listen(3001, () => console.log(&quot;API Server listening on port 3001&quot;));\n\n`, `40567668967029570000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">\n<span class=\"token keyword\">import</span> Koa <span class=\"token keyword\">from</span> <span class=\"token string\">\"koa\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> cors <span class=\"token keyword\">from</span> <span class=\"token string\">\"@koa/cors\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> supertokens <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> middleware <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/framework/koa\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> getWebsiteDomain<span class=\"token punctuation\">,</span> SuperTokensConfig <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"./config\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> KoaRouter <span class=\"token keyword\">from</span> <span class=\"token string\">\"koa-router\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> verifySession <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/recipe/session/framework/koa\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> SessionContext <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/framework/koa\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> Multitenancy <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node/recipe/multitenancy\"</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> deleteUser <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-node\"</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// basic structures to hold our metrics</span>\n<span class=\"token keyword\">interface</span> <span class=\"token class-name\">AuthAttempt</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">time</span><span class=\"token operator\">:</span> string<span class=\"token punctuation\">;</span>\n    <span class=\"token literal-property property\">userId</span><span class=\"token operator\">:</span> string<span class=\"token punctuation\">;</span>\n    <span class=\"token literal-property property\">status</span><span class=\"token operator\">:</span> string<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">const</span> authLogs <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">success</span><span class=\"token operator\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">recentAttempts</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token keyword\">as</span> AuthAttempt<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\nsupertokens<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span>SuperTokensConfig<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> app <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Koa</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> router <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">KoaRouter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\napp<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span>\n    <span class=\"token function\">cors</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n        <span class=\"token literal-property property\">origin</span><span class=\"token operator\">:</span> <span class=\"token function\">getWebsiteDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">allowHeaders</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"content-type\"</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">...</span>supertokens<span class=\"token punctuation\">.</span><span class=\"token function\">getAllCORSHeaders</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">credentials</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// This exposes all the APIs from SuperTokens to the client.</span>\napp<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span><span class=\"token function\">middleware</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// This endpoint can be accessed regardless of</span>\n<span class=\"token comment\">// having a session with SuperTokens</span>\nrouter<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"/hello\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token literal-property property\">ctx</span><span class=\"token operator\">:</span> SessionContext</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    ctx<span class=\"token punctuation\">.</span>body <span class=\"token operator\">=</span> <span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// An example API that requires session verification</span>\nrouter<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"/sessioninfo\"</span><span class=\"token punctuation\">,</span> <span class=\"token function\">verifySession</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token literal-property property\">ctx</span><span class=\"token operator\">:</span> SessionContext</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> userId <span class=\"token operator\">=</span> ctx<span class=\"token punctuation\">.</span>session<span class=\"token operator\">!</span><span class=\"token punctuation\">.</span><span class=\"token function\">getUserId</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    \n    <span class=\"token comment\">// Log successful authentication</span>\n    authLogs<span class=\"token punctuation\">.</span>success<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span>\n    authLogs<span class=\"token punctuation\">.</span>recentAttempts<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n        <span class=\"token literal-property property\">time</span><span class=\"token operator\">:</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toISOString</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        userId<span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">status</span><span class=\"token operator\">:</span> <span class=\"token string\">\"success\"</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    \n    ctx<span class=\"token punctuation\">.</span>status <span class=\"token operator\">=</span> <span class=\"token number\">200</span><span class=\"token punctuation\">;</span>\n    ctx<span class=\"token punctuation\">.</span>body <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n        userId<span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">status</span><span class=\"token operator\">:</span> <span class=\"token string\">\"ok\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">authStats</span><span class=\"token operator\">:</span> authLogs\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// This API is used by the frontend to create the tenants drop down when the app loads.</span>\n<span class=\"token comment\">// Depending on your UX, you can remove this API.</span>\nrouter<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"/tenants\"</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token literal-property property\">ctx</span><span class=\"token operator\">:</span> SessionContext</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> tenants <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> Multitenancy<span class=\"token punctuation\">.</span><span class=\"token function\">listAllTenants</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    ctx<span class=\"token punctuation\">.</span>body <span class=\"token operator\">=</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> tenants <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\napp<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span>router<span class=\"token punctuation\">.</span><span class=\"token function\">routes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>module<span class=\"token punctuation\">.</span>parent<span class=\"token punctuation\">)</span> app<span class=\"token punctuation\">.</span><span class=\"token function\">listen</span><span class=\"token punctuation\">(</span><span class=\"token number\">3001</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"API Server listening on port 3001\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n</code></pre></div>\n<p>Each recipe on the frontend <code class=\"language-text\">/frontend/src/config.tsx</code> has a <code class=\"language-text\">onHandleEvent</code> to help log what is currently happening in the system.</p>\n<p>Frontend <code class=\"language-text\">config.tsx</code></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"59349585916866494000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`\nimport EmailPassword from &quot;supertokens-auth-react/recipe/emailpassword&quot;;\nimport { EmailPasswordPreBuiltUI } from &quot;supertokens-auth-react/recipe/emailpassword/prebuiltui&quot;;\nimport Session from &quot;supertokens-auth-react/recipe/session&quot;;\n\nimport WebAuthn from &quot;supertokens-auth-react/recipe/webauthn&quot;; // passkeys\nimport { WebauthnPreBuiltUI } from 'supertokens-auth-react/recipe/webauthn/prebuiltui'; // passkeys\n\n// mfa\nimport MultiFactorAuth from &quot;supertokens-auth-react/recipe/multifactorauth&quot;;\nimport { MultiFactorAuthPreBuiltUI } from &quot;supertokens-auth-react/recipe/multifactorauth/prebuiltui&quot;;\nimport Passwordless from &quot;supertokens-auth-react/recipe/passwordless&quot;;\nimport { PasswordlessPreBuiltUI } from &quot;supertokens-auth-react/recipe/passwordless/prebuiltui&quot;;\nimport TOTP from &quot;supertokens-auth-react/recipe/totp&quot;;\nimport { TOTPPreBuiltUI } from &quot;supertokens-auth-react/recipe/totp/prebuiltui&quot;;\n\nexport function getApiDomain() {\n    const apiPort = import.meta.env.VITE_APP_API_PORT || 3001;\n    const apiUrl = import.meta.env.VITE_APP_API_URL || \\`http://localhost:\\${apiPort}\\`;\n    return apiUrl;\n}\n\nexport function getWebsiteDomain() {\n    const websitePort = import.meta.env.VITE_APP_WEBSITE_PORT || 3000;\n    const websiteUrl = import.meta.env.VITE_APP_WEBSITE_URL || \\`http://localhost:\\${websitePort}\\`;\n    return websiteUrl;\n}\n\nexport const SuperTokensConfig = {\n    appInfo: {\n        appName: &quot;SuperTokens Demo App&quot;,\n        apiDomain: getApiDomain(),\n        websiteDomain: getWebsiteDomain(),\n    },\n    // recipeList contains all the modules that you want to\n    // use from SuperTokens. See the full list here: https://supertokens.com/docs/guides\n    recipeList: [\n        EmailPassword.init(),\n        WebAuthn.init(),\n        Passwordless.init({\n            contactMethod: &quot;EMAIL_OR_PHONE&quot;,\n            onHandleEvent: (context) => {\n                // Track session events\n                if (context.action === &quot;SUCCESS&quot;) {\n                    if (context.createdNewSession) {\n                        let user = context.user;\n                        if (context.isNewRecipeUser && context.user.loginMethods.length === 1) {\n                            // sign up success\n                            console.log(&quot;sign up was a success&quot;)\n                        } else {\n                            // sign in success\n                            console.log(&quot;sign in was a success - no second auth&quot;)\n                        }\n                    } else {\n                        // during step up or second factor auth with email password\n                        console.log(&quot;sign in was a success - second factor auth&quot;)\n                    }\n                }\n            }\n        }),\n        MultiFactorAuth.init({ \n            firstFactors: [&quot;webauthn&quot;, &quot;emailpassword&quot;]\n        }),\n        TOTP.init(),\n        Session.init()\n    ],\n    getRedirectionURL: async (context) => {\n        if (context.action === &quot;SUCCESS&quot; && context.newSessionCreated) {\n            return &quot;/dashboard&quot;;\n        }\n    },\n};\n\nexport const recipeDetails = {\n    docsLink: &quot;https://supertokens.com/docs/emailpassword/introduction&quot;,\n};\n\nexport const PreBuiltUIList = [\n    EmailPasswordPreBuiltUI,\n    WebauthnPreBuiltUI,\n    PasswordlessPreBuiltUI,\n    MultiFactorAuthPreBuiltUI,\n    TOTPPreBuiltUI\n];\n\nexport const ComponentWrapper = (props: { children: JSX.Element }): JSX.Element => {\n    return props.children;\n};\n\n`, `59349585916866494000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">\n<span class=\"token keyword\">import</span> EmailPassword <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/emailpassword\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> EmailPasswordPreBuiltUI <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/emailpassword/prebuiltui\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> Session <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/session\"</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">import</span> WebAuthn <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/webauthn\"</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// passkeys</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> WebauthnPreBuiltUI <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'supertokens-auth-react/recipe/webauthn/prebuiltui'</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// passkeys</span>\n\n<span class=\"token comment\">// mfa</span>\n<span class=\"token keyword\">import</span> MultiFactorAuth <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/multifactorauth\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> MultiFactorAuthPreBuiltUI <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/multifactorauth/prebuiltui\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> Passwordless <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/passwordless\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> PasswordlessPreBuiltUI <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/passwordless/prebuiltui\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token constant\">TOTP</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/totp\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> TOTPPreBuiltUI <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"supertokens-auth-react/recipe/totp/prebuiltui\"</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">function</span> <span class=\"token function\">getApiDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> apiPort <span class=\"token operator\">=</span> <span class=\"token keyword\">import</span><span class=\"token punctuation\">.</span>meta<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_APP_API_PORT</span> <span class=\"token operator\">||</span> <span class=\"token number\">3001</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> apiUrl <span class=\"token operator\">=</span> <span class=\"token keyword\">import</span><span class=\"token punctuation\">.</span>meta<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_APP_API_URL</span> <span class=\"token operator\">||</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">http://localhost:</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>apiPort<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> apiUrl<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">function</span> <span class=\"token function\">getWebsiteDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> websitePort <span class=\"token operator\">=</span> <span class=\"token keyword\">import</span><span class=\"token punctuation\">.</span>meta<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_APP_WEBSITE_PORT</span> <span class=\"token operator\">||</span> <span class=\"token number\">3000</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> websiteUrl <span class=\"token operator\">=</span> <span class=\"token keyword\">import</span><span class=\"token punctuation\">.</span>meta<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">VITE_APP_WEBSITE_URL</span> <span class=\"token operator\">||</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">http://localhost:</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>websitePort<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> websiteUrl<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> SuperTokensConfig <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">appInfo</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token literal-property property\">appName</span><span class=\"token operator\">:</span> <span class=\"token string\">\"SuperTokens Demo App\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">apiDomain</span><span class=\"token operator\">:</span> <span class=\"token function\">getApiDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">websiteDomain</span><span class=\"token operator\">:</span> <span class=\"token function\">getWebsiteDomain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token comment\">// recipeList contains all the modules that you want to</span>\n    <span class=\"token comment\">// use from SuperTokens. See the full list here: https://supertokens.com/docs/guides</span>\n    <span class=\"token literal-property property\">recipeList</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n        EmailPassword<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        WebAuthn<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        Passwordless<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n            <span class=\"token literal-property property\">contactMethod</span><span class=\"token operator\">:</span> <span class=\"token string\">\"EMAIL_OR_PHONE\"</span><span class=\"token punctuation\">,</span>\n            <span class=\"token function-variable function\">onHandleEvent</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">context</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n                <span class=\"token comment\">// Track session events</span>\n                <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">.</span>action <span class=\"token operator\">===</span> <span class=\"token string\">\"SUCCESS\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n                    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">.</span>createdNewSession<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n                        <span class=\"token keyword\">let</span> user <span class=\"token operator\">=</span> context<span class=\"token punctuation\">.</span>user<span class=\"token punctuation\">;</span>\n                        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">.</span>isNewRecipeUser <span class=\"token operator\">&amp;&amp;</span> context<span class=\"token punctuation\">.</span>user<span class=\"token punctuation\">.</span>loginMethods<span class=\"token punctuation\">.</span>length <span class=\"token operator\">===</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n                            <span class=\"token comment\">// sign up success</span>\n                            console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"sign up was a success\"</span><span class=\"token punctuation\">)</span>\n                        <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n                            <span class=\"token comment\">// sign in success</span>\n                            console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"sign in was a success - no second auth\"</span><span class=\"token punctuation\">)</span>\n                        <span class=\"token punctuation\">}</span>\n                    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n                        <span class=\"token comment\">// during step up or second factor auth with email password</span>\n                        console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"sign in was a success - second factor auth\"</span><span class=\"token punctuation\">)</span>\n                    <span class=\"token punctuation\">}</span>\n                <span class=\"token punctuation\">}</span>\n            <span class=\"token punctuation\">}</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        MultiFactorAuth<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> \n            <span class=\"token literal-property property\">firstFactors</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"webauthn\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"emailpassword\"</span><span class=\"token punctuation\">]</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token constant\">TOTP</span><span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        Session<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">getRedirectionURL</span><span class=\"token operator\">:</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">context</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">.</span>action <span class=\"token operator\">===</span> <span class=\"token string\">\"SUCCESS\"</span> <span class=\"token operator\">&amp;&amp;</span> context<span class=\"token punctuation\">.</span>newSessionCreated<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            <span class=\"token keyword\">return</span> <span class=\"token string\">\"/dashboard\"</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> recipeDetails <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">docsLink</span><span class=\"token operator\">:</span> <span class=\"token string\">\"https://supertokens.com/docs/emailpassword/introduction\"</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> PreBuiltUIList <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n    EmailPasswordPreBuiltUI<span class=\"token punctuation\">,</span>\n    WebauthnPreBuiltUI<span class=\"token punctuation\">,</span>\n    PasswordlessPreBuiltUI<span class=\"token punctuation\">,</span>\n    MultiFactorAuthPreBuiltUI<span class=\"token punctuation\">,</span>\n    TOTPPreBuiltUI\n<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> ComponentWrapper <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>props<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">children</span><span class=\"token operator\">:</span> <span class=\"token constant\">JSX</span><span class=\"token punctuation\">.</span>Element <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> <span class=\"token constant\">JSX</span><span class=\"token punctuation\">.</span><span class=\"token parameter\">Element</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> props<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n</code></pre></div>\n<h3 id=\"how-this-setup-prevents-a-phishing-attack\" style=\"position:relative;\"><a href=\"#how-this-setup-prevents-a-phishing-attack\" aria-label=\"how this setup prevents a phishing attack permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How this setup prevents a phishing attack</h3>\n<p>Traditional authentication methods are vulnerable because they rely on shared secrets that can be intercepted. To illustrate how the WebAuthn implementation protects against these attacks, let’s simulate a common phishing scenario and see how our SuperTokens + WebAuthn setup renders it ineffective.</p>\n<p>In a typical phishing attack targeting traditional MFA:</p>\n<ol>\n<li>An attacker creates a convincing clone of your login page</li>\n<li>They send users a link to this fake site (e.g., <code class=\"language-text\">my-legit-app-secure.com</code> instead of <code class=\"language-text\">mylegitapp.com</code>)</li>\n<li>When users enter credentials and MFA codes, the attacker captures them in real-time</li>\n<li>The attacker uses these stolen credentials to access the real site</li>\n</ol>\n<p>Even with traditional MFA like SMS codes or authenticator apps, this attack works because the attacker can simply forward the stolen credentials and MFA codes to the legitimate service immediately after capturing them.</p>\n<p>This isn’t just theoretical protection. Remember the Cloudflare incident mentioned earlier? Their own security report explicitly stated that employees using FIDO2-based WebAuthn keys (the same standard we’re implementing) remained protected while those using push notifications were compromised.</p>\n<p>By requiring phishing-resistant MFA with WebAuthn as we’ve implemented, you’re effectively removing phishing as a viable attack vector against your authentication system. Even if users are tricked into visiting a fake site, the browser’s security model prevents the attack from succeeding.</p>\n<h2 id=\"how-supertokens-elevates-phishing-resistant-mfa\" style=\"position:relative;\"><a href=\"#how-supertokens-elevates-phishing-resistant-mfa\" aria-label=\"how supertokens elevates phishing resistant mfa permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How SuperTokens Elevates Phishing-Resistant MFA</h2>\n<h3 id=\"why-use-supertokens-instead-of-rolling-your-own\" style=\"position:relative;\"><a href=\"#why-use-supertokens-instead-of-rolling-your-own\" aria-label=\"why use supertokens instead of rolling your own permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why Use SuperTokens Instead of Rolling Your Own?</h3>\n<p>Authentication seems straightforward on the surface—verify identity and grant access—but implementing it securely involves intricate technical challenges. Many developers underestimate these complexities until they encounter serious security issues in production.</p>\n<p>Building your own authentication system from scratch requires managing numerous critical components:</p>\n<ol>\n<li><strong>Security vulnerabilities</strong>: Without specialized knowledge, your system could be vulnerable to common attacks like CSRF, XSS, session fixation, and credential stuffing</li>\n<li><strong>Compliance requirements</strong>: Meeting standards like GDPR, HIPAA, SOC2, and other regulations requires domain expertise that’s expensive to develop and maintain in-house</li>\n<li><strong>Ongoing maintenance</strong>: Authentication isn’t a “build once and forget” feature—it requires constant updates to address evolving security threats and browser compatibility issues</li>\n<li><strong>Developer resources</strong>: Building robust authentication diverts valuable engineering time from your core product features and business logic</li>\n<li><strong>Edge cases</strong>: Authentication has countless edge cases around account recovery, device management, and session handling that you’ll need to solve</li>\n</ol>\n<h3 id=\"supertokens-advanced-security-features-for-phishing-resistant-mfa\" style=\"position:relative;\"><a href=\"#supertokens-advanced-security-features-for-phishing-resistant-mfa\" aria-label=\"supertokens advanced security features for phishing resistant mfa permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>SuperTokens’ Advanced Security Features for Phishing-Resistant MFA</h3>\n<p>Modern authentication systems rely on tokens to maintain user sessions, but these tokens become prime targets for attackers. SuperTokens implements sophisticated session management that mitigates token theft.</p>\n<p>SuperTokens implements automatic token rotation, significantly reducing the window of opportunity for attackers if a token is somehow compromised:</p>\n<ul>\n<li>Access tokens have short lifespans</li>\n<li>Refresh tokens are automatically rotated with each use</li>\n<li>The rotation system maintains session continuity while limiting exposure</li>\n</ul>\n<h3 id=\"seamless-integration-with-webauthn--fido2\" style=\"position:relative;\"><a href=\"#seamless-integration-with-webauthn--fido2\" aria-label=\"seamless integration with webauthn  fido2 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Seamless Integration with WebAuthn &#x26; FIDO2</h3>\n<p>SuperTokens’ implementation creates a frictionless bridge between traditional authentication flows and phishing-resistant standards. This means users can authenticate using:</p>\n<ul>\n<li>Built-in biometrics (TouchID, FaceID, Windows Hello)</li>\n<li>Platform authenticators (Android/Iphone fingerprint sensors)</li>\n<li>External security keys (YubiKey, Titan Security Key)</li>\n</ul>\n<h3 id=\"flexible-architecture-enforce-mfa-for-specific-usersroles\" style=\"position:relative;\"><a href=\"#flexible-architecture-enforce-mfa-for-specific-usersroles\" aria-label=\"flexible architecture enforce mfa for specific usersroles permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Flexible Architecture: Enforce MFA for Specific Users/Roles</h3>\n<p>SuperTokens provides granular control over authentication requirements without complex custom code. With Role-Based MFA Policies you can implement different security requirements based on user roles. This enables you to:</p>\n<ul>\n<li>Enforce hardware security keys for administrators</li>\n<li>Require second factors only for sensitive operations</li>\n<li>Implement different policies based on user risk profiles</li>\n</ul>\n<p>SuperTokens makes it easy to require additional authentication for specific actions. This allows you to:</p>\n<ul>\n<li>Require additional factors for high-value transactions</li>\n<li>Implement risk-based authentication policies</li>\n<li>Verify identity before sensitive account changes</li>\n</ul>\n<p>The system handles common edge cases like authenticator loss. This provides secure recovery options while maintaining security:</p>\n<ul>\n<li>Email/phone fallback mechanisms</li>\n<li>Backup code generation for account recovery</li>\n<li>Administrator-assisted recovery workflows</li>\n</ul>\n<p>By leveraging SuperTokens’ flexible architecture, you can implement authentication policies that balance security with usability, applying the appropriate level of protection based on user role, action sensitivity, and risk assessment.</p>\n<p>In the next section, we’ll explore how to deploy this phishing-resistant MFA system at scale and integrate it with existing infrastructure.</p>\n<h2 id=\"final-thoughts--next-steps\" style=\"position:relative;\"><a href=\"#final-thoughts--next-steps\" aria-label=\"final thoughts  next steps permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Final Thoughts &#x26; Next Steps</h2>\n<h3 id=\"taking-phishing-resistant-authentication-to-the-next-level\" style=\"position:relative;\"><a href=\"#taking-phishing-resistant-authentication-to-the-next-level\" aria-label=\"taking phishing resistant authentication to the next level permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Taking Phishing-Resistant Authentication to the Next Level</h3>\n<p>For organizations with stringent security requirements, SuperTokens offers device attestation capabilities that can be leveraged for:</p>\n<ul>\n<li>Verifies authenticator is from a trusted manufacturer</li>\n<li>Ensures hardware-backed key storage</li>\n<li>Requires user verification (biometric or PIN)</li>\n<li>Prevents credential cloning between devices</li>\n</ul>\n<p>Device attestation enables security teams to enforce hardware security key policies and maintain an audit trail of registered authenticators—critical for regulated industries.</p>\n<h3 id=\"encouraging-user-adoption-making-webauthn-onboarding-seamless\" style=\"position:relative;\"><a href=\"#encouraging-user-adoption-making-webauthn-onboarding-seamless\" aria-label=\"encouraging user adoption making webauthn onboarding seamless permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Encouraging User Adoption: Making WebAuthn Onboarding Seamless</h3>\n<p>The most secure authentication is useless if users can’t or won’t use it. SuperTokens provides customizable UI components that guide users through adopting phishing-resistant authentication, making the entire process as low friction as possible.</p>\n<p>Best practices for increasing adoption include:</p>\n<ul>\n<li>Explaining the possible costs that come with a phishing attack</li>\n<li>Creating fallback mechanisms for lost devices</li>\n<li>Gradually transitioning from traditional MFA to phishing-resistant options</li>\n</ul>\n<h2 id=\"further-reading-supertokens-documentation\" style=\"position:relative;\"><a href=\"#further-reading-supertokens-documentation\" aria-label=\"further reading supertokens documentation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Further Reading: SuperTokens Documentation</strong></h2>\n<p>The implementation we’ve explored is just the beginning. SuperTokens offers extensive documentation for advanced configurations:</p>\n<ul>\n<li><a href=\"https://supertokens.com/docs/authentication/passkeys/initial-setup\" target=\"_blank\" rel=\"nofollow\">WebAuthn Implementation Guide</a> - Detailed setup instructions</li>\n<li><a href=\"https://supertokens.com/docs/additional-verification/mfa/initial-setup\" target=\"_blank\" rel=\"nofollow\">Multi-factor Authentication</a> - Advanced policies and flows</li>\n<li><a href=\"https://supertokens.com/docs/userroles/introduction\" target=\"_blank\" rel=\"nofollow\">User Roles and Permissions</a> - Role-based authentication requirements</li>\n</ul>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Conclusion</strong></h2>\n<p>By implementing phishing-resistant MFA with SuperTokens and WebAuthn, you’ve addressed one of the most persistent security vulnerabilities facing modern applications. This approach not only protects your users from sophisticated attacks but also improves their authentication experience.</p>\n<p>The combination of SuperTokens’ flexible architecture, WebAuthn’s cryptographic security, and the FIDO2 standards creates a defense-in-depth strategy that eliminates entire categories of authentication attacks while providing the granular control needed to balance security with usability.</p>\n<p>As phishing attacks continue to evolve in sophistication, this implementation ensures your authentication system remains resilient against current and future threats.</p>\n<h3 id=\"\" style=\"position:relative;\"><a href=\"#\" aria-label=\" permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h3>","frontmatter":{"date":"May 06, 2025","title":"Implementing Phishing-Resistant MFA: Hands-On Developer Guide","cover":"Implementing-Phishing-Resistant-MFA.png","author":"Maurice Saldivar","description":"Learn how to implement phishing-resistant MFA with FIDO2, WebAuthn, and SuperTokens. Step-by-step tutorial for secure, developer-friendly authentication."},"fields":{"slug":"/phishing-resistant-mfa/"}},"site":{"siteMetadata":{"title":"SuperTokens Blog"}}},"pageContext":{"id":"61890d1b-5d87-5b6d-9e83-30f65c8ecb19","fields__slug":"/phishing-resistant-mfa/","__params":{"fields__slug":"phishing-resistant-mfa"}}},
    "staticQueryHashes": []}