diff --git a/v2/emailpassword/common-customizations/embed-sign-in-up-form.mdx b/v2/emailpassword/common-customizations/embed-sign-in-up-form.mdx index 1e7751519..77b944af4 100644 --- a/v2/emailpassword/common-customizations/embed-sign-in-up-form.mdx +++ b/v2/emailpassword/common-customizations/embed-sign-in-up-form.mdx @@ -10,22 +10,38 @@ import TabItem from '@theme/TabItem'; import {Question, Answer}from "/src/components/question" import RRDVersionSubTabs from "/src/components/tabs/RRDVersionSubTabs" -# Embed Sign In / Up form in a page +# Embed Sign In / Up form in a page -## Step 1: Disable default implementation +## Case 1: Rendering the Auth Widget in a page -This will prevent SuperTokens from displaying the default login UI in the `/auth` page. +The following example shows the scenario where you have a dedicated route, such as `/auth`, for rendering the Auth Widget. Upon a successful login, the user will be automatically redirected to the return value of `getRedirectionURL` (defaulting to `/`). + + + + + + ```tsx +import React from "react"; import SuperTokens from "supertokens-auth-react"; import EmailPassword from "supertokens-auth-react/recipe/emailpassword"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/emailpassword/prebuiltui'; +// highlight-end +// @ts-ignore +import Header from "./header"; +// @ts-ignore +import Footer from "./footer"; +import { useNavigate } from "react-router-dom"; SuperTokens.init({ appInfo: { @@ -37,23 +53,188 @@ SuperTokens.init({ EmailPassword.init({ signInAndUpFeature: { // highlight-next-line - disableDefaultUI: true, - // ... + disableDefaultUI: true, // This will prevent SuperTokens from displaying the default login UI in the `/auth` page. }, + // highlight-start + async getRedirectionURL(context) { + if (context.action === "SUCCESS") { + return "/dashboard"; // defaults to "/" + }; + }, + // highlight-end // ... }), // ... - ] + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +function AuthPage() { + const navigate = useNavigate(); + return ( +
+
+ // highlight-next-line + +
+
+ ); +} +``` + +
+ + + +```tsx +import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import EmailPassword from "supertokens-auth-react/recipe/emailpassword"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/emailpassword/prebuiltui'; +// highlight-end +// @ts-ignore +import Header from "./header"; +// @ts-ignore +import Footer from "./footer"; +import { useHistory } from "react-router-dom5"; + +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + EmailPassword.init({ + signInAndUpFeature: { + // highlight-next-line + disableDefaultUI: true, // This will prevent SuperTokens from displaying the default login UI in the `/auth` page. + }, + // highlight-start + async getRedirectionURL(context) { + if (context.action === "SUCCESS") { + return "/dashboard"; // defaults to "/" + }; + }, + // highlight-end + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end }); + +function AuthPage() { + const history = useHistory(); + return ( +
+
+ // highlight-next-line + +
+
+ ); +} ``` + +
+ +
+ +
+ + +```tsx +import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import EmailPassword from "supertokens-auth-react/recipe/emailpassword"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/emailpassword/prebuiltui'; +// highlight-end +// @ts-ignore +import Header from "./header"; +// @ts-ignore +import Footer from "./footer"; + +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + EmailPassword.init({ + signInAndUpFeature: { + // highlight-next-line + disableDefaultUI: true, // This will prevent SuperTokens from displaying the default login UI in the `/auth` page. + }, + // highlight-start + async getRedirectionURL(context) { + if (context.action === "SUCCESS") { + return "/dashboard"; // defaults to "/" + }; + }, + // highlight-end + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +function AuthPage() { + return ( +
+
+ // highlight-next-line + +
+
+ ) +} +``` +
+
-If you navigate to `/auth`, you should not see the widget anymore. +In the above code snippet, we: -## Step 2: Render the component yourself +1. Disabled the default Auth UI by setting `disableDefaultUI` to `true` inside the EmailPassword recipe config. +2. Overrode the `getRedirectionURL` function inside the EmailPassword recipe config to redirect to `/dashboard` upon successful login. +3. Overrode the `getRedirectionURL` function inside the SuperTokens config to redirect to `/auth` when login is required. -For example if you would like to show the login form in our own component which renders custom UI around it, and is shown only if the user is logged in, then we can: +Feel free to customize the redirection URLs as needed. + +:::note +When the user visits the `/auth` page, they will see the SignIn UI by default. To render the SignUp UI, append `show=signup` as a query parameter to the URL, like`/auth?show=signup`. +::: + +## Case 2: Rendering the Auth Widget in a page with no redirection + +The following example shows the scenario where you have a dedicated route, such as `/auth`, for rendering the Auth Widget. However, upon a successful login, the user will see a logged in UI instead of getting redirected. @@ -67,6 +248,8 @@ For example if you would like to show the login form in our own component which ```tsx import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import EmailPassword from "supertokens-auth-react/recipe/emailpassword"; // highlight-start import { SignInAndUp } from 'supertokens-auth-react/recipe/emailpassword/prebuiltui'; import Session from "supertokens-auth-react/recipe/session"; @@ -77,7 +260,30 @@ import Header from "./header"; import Footer from "./footer"; import { useNavigate } from "react-router-dom"; -function MyLandingPage() { +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + EmailPassword.init({ + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +// highlight-start +function LandingPage() { let sessionContext = Session.useSessionContext(); const navigate = useNavigate(); if (sessionContext.loading) { @@ -107,6 +313,7 @@ function MyLandingPage() { ) } } +// highlight-end ``` @@ -115,6 +322,8 @@ function MyLandingPage() { ```tsx import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import EmailPassword from "supertokens-auth-react/recipe/emailpassword"; // highlight-start import { SignInAndUp } from 'supertokens-auth-react/recipe/emailpassword/prebuiltui'; import Session from "supertokens-auth-react/recipe/session"; @@ -123,9 +332,32 @@ import Session from "supertokens-auth-react/recipe/session"; import Header from "./header"; // @ts-ignore import Footer from "./footer"; -import { useHistory } from 'react-router-dom5'; +import { useHistory } from "react-router-dom5"; + +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + EmailPassword.init({ + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); -function MyLandingPage() { +// highlight-start +function LandingPage() { let sessionContext = Session.useSessionContext(); const history = useHistory(); if (sessionContext.loading) { @@ -155,6 +387,7 @@ function MyLandingPage() { ) } } +// highlight-end ``` @@ -164,9 +397,10 @@ function MyLandingPage() { - ```tsx import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import EmailPassword from "supertokens-auth-react/recipe/emailpassword"; // highlight-start import { SignInAndUp } from 'supertokens-auth-react/recipe/emailpassword/prebuiltui'; import Session from "supertokens-auth-react/recipe/session"; @@ -176,7 +410,30 @@ import Header from "./header"; // @ts-ignore import Footer from "./footer"; -function MyLandingPage() { +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + EmailPassword.init({ + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +// highlight-start +function LandingPage() { let sessionContext = Session.useSessionContext(); if (sessionContext.loading) { return null; @@ -205,59 +462,203 @@ function MyLandingPage() { ) } } +// highlight-end ``` - - -## Step 3: Changing the website path for the login UI +In the above code snippet, we wrap the logged-in component with `Session.SessionAuth` to validate all claims before displaying the logged-in UI. For instance, with email verification enabled, if a user's email is unverified, `Session.SessionAuth` redirects to the email verification page. -The default path for this is component is `/{websiteBasePath}/`. +:::note +In the above case, redirection may occur if a claim fails. For instance, in the case of an Email Verification claim, if the user's email is not verified, they will be redirected to the email verification page. To prevent redirection for failed claims, please contact us on [Discord](https://supertokens.com/discord) for assistance. +::: -If you are displaying this at some custom path, then you need add additional config on frontend: +## Case 3: Rendering the Auth Widget in a popup + +The following example shows the scenario where you embed the Auth Widget in a popup, and upon successful login, you aim to close the popup. + + + + + + ```tsx +import React, { useState, useEffect } from "react"; +import Modal from "react-modal"; import SuperTokens from "supertokens-auth-react"; import EmailPassword from "supertokens-auth-react/recipe/emailpassword"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/emailpassword/prebuiltui'; +import Session from "supertokens-auth-react/recipe/session"; +// highlight-end +import { useNavigate } from "react-router-dom"; SuperTokens.init({ appInfo: { apiDomain: "...", appName: "...", - websiteDomain: "...", + websiteDomain: "..." }, recipeList: [ - EmailPassword.init() - ], - //highlight-start - // The user will be taken to the custom path when then need to login. - getRedirectionURL: async (context) => { - if (context.action === "TO_AUTH") { - return "/custom-login-path"; - }; + EmailPassword.init({ + // ... + }), + // ... + ] +}); + +function AuthPopup() { + let sessionContext = Session.useSessionContext(); + const navigate = useNavigate(); + const [isModalOpen, setIsModalOpen] = useState(false); + + const openModal = () => setIsModalOpen(true); + const closeModal = () => setIsModalOpen(false); + + useEffect(() => { + if (sessionContext.loading) { + return; + } + if (sessionContext.doesSessionExist) { + closeModal(); + } else { + openModal(); } - //highlight-end -}) + }, [sessionContext]); + + if (sessionContext.loading) { + return null; + } + + return ( +
+ {sessionContext.doesSessionExist && ( + // We wrap this with so that + // all claims are validated before showing the logged in UI. + // For example, if email verification is switched on, and + // the user's email is not verified, then + // will redirect to the email verification page. + +

You are logged In!

+

UserId: {sessionContext.userId}

+ +
+ )} + + + {/* highlight-next-line */} + + +
+ ); +} ``` +
-
-## Optional: Prevent redirection after SignIn / Up + -Upon successful login, SuperTokens redirects the user to the return value of `getRedirectionURL` provided in the recipe config. By default or when returning `undefined` from `getRedirectionURL`, the user is redirected to the `/` route. If you wish to completely prevent redirection, return `null` instead. Typically, this is used if you want to embed the sign in / up component in a popup and want to just dismiss the popup post login. +```tsx +import React, { useState, useEffect } from "react"; +import Modal from "react-modal"; +import SuperTokens from "supertokens-auth-react"; +import EmailPassword from "supertokens-auth-react/recipe/emailpassword"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/emailpassword/prebuiltui'; +import Session from "supertokens-auth-react/recipe/session"; +// highlight-end +import { useHistory } from "react-router-dom5"; - - +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + EmailPassword.init({ + // ... + }), + // ... + ] +}); + +function AuthPopup() { + let sessionContext = Session.useSessionContext(); + const history = useHistory(); + const [isModalOpen, setIsModalOpen] = useState(false); + + const openModal = () => setIsModalOpen(true); + const closeModal = () => setIsModalOpen(false); + + useEffect(() => { + if (sessionContext.loading) { + return; + } + if (sessionContext.doesSessionExist) { + closeModal(); + } else { + openModal(); + } + }, [sessionContext]); + + if (sessionContext.loading) { + return null; + } + + return ( +
+ {sessionContext.doesSessionExist && ( + // We wrap this with so that + // all claims are validated before showing the logged in UI. + // For example, if email verification is switched on, and + // the user's email is not verified, then + // will redirect to the email verification page. + +

You are logged In!

+

UserId: {sessionContext.userId}

+ +
+ )} + + + {/* highlight-next-line */} + + +
+ ); +} +``` + +
+ + + + + ```tsx +import React, { useState, useEffect } from "react"; +import Modal from "react-modal"; import SuperTokens from "supertokens-auth-react"; import EmailPassword from "supertokens-auth-react/recipe/emailpassword"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/emailpassword/prebuiltui'; +import Session from "supertokens-auth-react/recipe/session"; +// highlight-end SuperTokens.init({ appInfo: { @@ -267,29 +668,69 @@ SuperTokens.init({ }, recipeList: [ EmailPassword.init({ - //highlight-start - getRedirectionURL: async (context) => { - // Prevent redirection after successful sign in/up by returning null. - if (context.action === "SUCCESS") { - return null; - }; - }, - //highlight-end - }) - ], -}) + // ... + }), + // ... + ] +}); + +function AuthPopup() { + let sessionContext = Session.useSessionContext(); + const [isModalOpen, setIsModalOpen] = useState(false); + + const openModal = () => setIsModalOpen(true); + const closeModal = () => setIsModalOpen(false); + + useEffect(() => { + if (sessionContext.loading) { + return; + } + if (sessionContext.doesSessionExist) { + closeModal(); + } else { + openModal(); + } + }, [sessionContext]); + + if (sessionContext.loading) { + return null; + } + + return ( +
+ {sessionContext.doesSessionExist && ( + // We wrap this with so that + // all claims are validated before showing the logged in UI. + // For example, if email verification is switched on, and + // the user's email is not verified, then + // will redirect to the email verification page. + +

You are logged In!

+

UserId: {sessionContext.userId}

+ +
+ )} + + + {/* highlight-next-line */} + + +
+ ); +} ``` +
+
:::note -To avoid redirection for failed claims, such as Email Verification, reach out to us on [Discord](https://supertokens.com/discord) for assistance. +In the above case, redirection may occur if a claim fails. For instance, in the case of an Email Verification claim, if the user's email is not verified, they will be redirected to the email verification page. To prevent redirection for failed claims, please contact us on [Discord](https://supertokens.com/discord) for assistance. ::: -## Optional: Rendering Auth components together in a popup and page - -You may choose to display the Auth UI in a full page and in a popup in the same app. For the full-page Auth UI, redirection after a successful login is preferred, whereas in the popup, it is not. In this scenario, you have the option to check either the current URL or the `userContext` object in `getRedirectionURL` to decide whether to return null or not. -
diff --git a/v2/passwordless/common-customizations/embed-sign-in-up-form.mdx b/v2/passwordless/common-customizations/embed-sign-in-up-form.mdx index 4babc7e73..b51d8882e 100644 --- a/v2/passwordless/common-customizations/embed-sign-in-up-form.mdx +++ b/v2/passwordless/common-customizations/embed-sign-in-up-form.mdx @@ -10,22 +10,38 @@ import TabItem from '@theme/TabItem'; import {Question, Answer}from "/src/components/question" import RRDVersionSubTabs from "/src/components/tabs/RRDVersionSubTabs" -# Embed Sign In / Up form in a page +# Embed Sign In / Up form in a page -## Step 1: Disable default implementation +## Case 1: Rendering the Auth Widget in a page -This will prevent SuperTokens from displaying the default login UI in the `/auth` page. +The following example shows the scenario where you have a dedicated route, such as `/auth`, for rendering the Auth Widget. Upon a successful login, the user will be automatically redirected to the return value of `getRedirectionURL` (defaulting to `/`). + + + + + + ```tsx +import React from "react"; import SuperTokens from "supertokens-auth-react"; import Passwordless from "supertokens-auth-react/recipe/passwordless"; +// highlight-start +import { SignInUp } from 'supertokens-auth-react/recipe/passwordless/prebuiltui'; +// highlight-end +// @ts-ignore +import Header from "./header"; +// @ts-ignore +import Footer from "./footer"; +import { useNavigate } from "react-router-dom"; SuperTokens.init({ appInfo: { @@ -38,24 +54,190 @@ SuperTokens.init({ contactMethod: "EMAIL", // This example will work with any contactMethod signInUpFeature: { // highlight-next-line - disableDefaultUI: true, - // ... + disableDefaultUI: true, // This will prevent SuperTokens from displaying the default login UI in the `/auth` page. }, + // highlight-start + async getRedirectionURL(context) { + if (context.action === "SUCCESS") { + return "/dashboard"; // defaults to "/" + }; + }, + // highlight-end // ... }), // ... - ] + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end }); + +function AuthPage() { + const navigate = useNavigate(); + return ( +
+
+ // highlight-next-line + +
+
+ ); +} ``` -If you navigate to `/auth`, you should not see the widget anymore. +
+ + + +```tsx +import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import Passwordless from "supertokens-auth-react/recipe/passwordless"; +// highlight-start +import { SignInUp } from 'supertokens-auth-react/recipe/passwordless/prebuiltui'; +// highlight-end +// @ts-ignore +import Header from "./header"; +// @ts-ignore +import Footer from "./footer"; +import { useHistory } from "react-router-dom5"; + +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + Passwordless.init({ + contactMethod: "EMAIL", // This example will work with any contactMethod + signInUpFeature: { + // highlight-next-line + disableDefaultUI: true, // This will prevent SuperTokens from displaying the default login UI in the `/auth` page. + }, + // highlight-start + async getRedirectionURL(context) { + if (context.action === "SUCCESS") { + return "/dashboard"; // defaults to "/" + }; + }, + // highlight-end + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +function AuthPage() { + const history = useHistory(); + return ( +
+
+ // highlight-next-line + +
+
+ ); +} +``` + +
+ +
+ +
+ + +```tsx +import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import Passwordless from "supertokens-auth-react/recipe/passwordless"; +// highlight-start +import { SignInUp } from 'supertokens-auth-react/recipe/passwordless/prebuiltui'; +// highlight-end +// @ts-ignore +import Header from "./header"; +// @ts-ignore +import Footer from "./footer"; + +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + Passwordless.init({ + contactMethod: "EMAIL", // This example will work with any contactMethod + signInUpFeature: { + // highlight-next-line + disableDefaultUI: true, // This will prevent SuperTokens from displaying the default login UI in the `/auth` page. + }, + // highlight-start + async getRedirectionURL(context) { + if (context.action === "SUCCESS") { + return "/dashboard"; // defaults to "/" + }; + }, + // highlight-end + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); +function AuthPage() { + return ( +
+
+ // highlight-next-line + +
+
+ ) +} +``` +
+
-## Step 2: Render the component yourself +In the above code snippet, we: + +1. Disabled the default Auth UI by setting `disableDefaultUI` to `true` inside the Passwordless recipe config. +2. Overrode the `getRedirectionURL` function inside the Passwordless recipe config to redirect to `/dashboard` upon successful login. +3. Overrode the `getRedirectionURL` function inside the SuperTokens config to redirect to `/auth` when login is required. -For example if you would like to show the login form in our own component which renders custom UI around it, and is shown only if the user is logged in, then we can: +Feel free to customize the redirection URLs as needed. + +:::note +When the user visits the `/auth` page, they will see the SignIn UI by default. To render the SignUp UI, append `show=signup` as a query parameter to the URL, like`/auth?show=signup`. +::: + +## Case 2: Rendering the Auth Widget in a page with no redirection + +The following example shows the scenario where you have a dedicated route, such as `/auth`, for rendering the Auth Widget. However, upon a successful login, the user will see a logged in UI instead of getting redirected. @@ -69,6 +251,8 @@ For example if you would like to show the login form in our own component which ```tsx import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import Passwordless from "supertokens-auth-react/recipe/passwordless"; // highlight-start import { SignInUp } from 'supertokens-auth-react/recipe/passwordless/prebuiltui'; import Session from "supertokens-auth-react/recipe/session"; @@ -79,7 +263,31 @@ import Header from "./header"; import Footer from "./footer"; import { useNavigate } from "react-router-dom"; -function MyLandingPage() { +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + Passwordless.init({ + contactMethod: "EMAIL", // This example will work with any contactMethod + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +// highlight-start +function LandingPage() { let sessionContext = Session.useSessionContext(); const navigate = useNavigate(); if (sessionContext.loading) { @@ -109,6 +317,7 @@ function MyLandingPage() { ) } } +// highlight-end ``` @@ -117,6 +326,8 @@ function MyLandingPage() { ```tsx import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import Passwordless from "supertokens-auth-react/recipe/passwordless"; // highlight-start import { SignInUp } from 'supertokens-auth-react/recipe/passwordless/prebuiltui'; import Session from "supertokens-auth-react/recipe/session"; @@ -127,7 +338,31 @@ import Header from "./header"; import Footer from "./footer"; import { useHistory } from "react-router-dom5"; -function MyLandingPage() { +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + Passwordless.init({ + contactMethod: "EMAIL", // This example will work with any contactMethod + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +// highlight-start +function LandingPage() { let sessionContext = Session.useSessionContext(); const history = useHistory(); if (sessionContext.loading) { @@ -157,6 +392,7 @@ function MyLandingPage() { ) } } +// highlight-end ``` @@ -166,9 +402,10 @@ function MyLandingPage() { - ```tsx import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import Passwordless from "supertokens-auth-react/recipe/passwordless"; // highlight-start import { SignInUp } from 'supertokens-auth-react/recipe/passwordless/prebuiltui'; import Session from "supertokens-auth-react/recipe/session"; @@ -178,7 +415,31 @@ import Header from "./header"; // @ts-ignore import Footer from "./footer"; -function MyLandingPage() { +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + Passwordless.init({ + contactMethod: "EMAIL", // This example will work with any contactMethod + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +// highlight-start +function LandingPage() { let sessionContext = Session.useSessionContext(); if (sessionContext.loading) { return null; @@ -207,25 +468,43 @@ function MyLandingPage() { ) } } +// highlight-end ``` - -## Step 3: Changing the website path for the login UI +In the above code snippet, we wrap the logged-in component with `Session.SessionAuth` to validate all claims before displaying the logged-in UI. For instance, with email verification enabled, if a user's email is unverified, `Session.SessionAuth` redirects to the email verification page. + +:::note +In the above case, redirection may occur if a claim fails. For instance, in the case of an Email Verification claim, if the user's email is not verified, they will be redirected to the email verification page. To prevent redirection for failed claims, please contact us on [Discord](https://supertokens.com/discord) for assistance. +::: -The default path for this is component is `/{websiteBasePath}/`. +## Case 3: Rendering the Auth Widget in a popup -If you are displaying this at some custom path, then you need add additional config on frontend: +The following example shows the scenario where you embed the Auth Widget in a popup, and upon successful login, you aim to close the popup. + + + + + + ```tsx +import React, { useState, useEffect } from "react"; +import Modal from "react-modal"; import SuperTokens from "supertokens-auth-react"; import Passwordless from "supertokens-auth-react/recipe/passwordless"; +// highlight-start +import { SignInUp } from 'supertokens-auth-react/recipe/passwordless/prebuiltui'; +import Session from "supertokens-auth-react/recipe/session"; +// highlight-end +import { useNavigate } from "react-router-dom"; SuperTokens.init({ appInfo: { @@ -236,31 +515,158 @@ SuperTokens.init({ recipeList: [ Passwordless.init({ contactMethod: "EMAIL", // This example will work with any contactMethod - }) - ], - //highlight-start - // The user will be taken to the custom path when then need to login. - getRedirectionURL: async (context) => { - if (context.action === "TO_AUTH") { - return "/custom-login-path"; - }; + // ... + }), + // ... + ] +}); + +function AuthPopup() { + let sessionContext = Session.useSessionContext(); + const navigate = useNavigate(); + const [isModalOpen, setIsModalOpen] = useState(false); + + const openModal = () => setIsModalOpen(true); + const closeModal = () => setIsModalOpen(false); + + useEffect(() => { + if (sessionContext.loading) { + return; } - //highlight-end -}) + if (sessionContext.doesSessionExist) { + closeModal(); + } else { + openModal(); + } + }, [sessionContext]); + + if (sessionContext.loading) { + return null; + } + + return ( +
+ {sessionContext.doesSessionExist && ( + // We wrap this with so that + // all claims are validated before showing the logged in UI. + // For example, if email verification is switched on, and + // the user's email is not verified, then + // will redirect to the email verification page. + +

You are logged In!

+

UserId: {sessionContext.userId}

+ +
+ )} + + + {/* highlight-next-line */} + + +
+ ); +} ``` +
-
-## Optional: Prevent redirection after SignIn / Up + -Upon successful login, SuperTokens redirects the user to the return value of `getRedirectionURL` provided in the recipe config. By default or when returning `undefined` from `getRedirectionURL`, the user is redirected to the `/` route. If you wish to completely prevent redirection, return `null` instead. Typically, this is used if you want to embed the sign in / up component in a popup and want to just dismiss the popup post login. +```tsx +import React, { useState, useEffect } from "react"; +import Modal from "react-modal"; +import SuperTokens from "supertokens-auth-react"; +import Passwordless from "supertokens-auth-react/recipe/passwordless"; +// highlight-start +import { SignInUp } from 'supertokens-auth-react/recipe/passwordless/prebuiltui'; +import Session from "supertokens-auth-react/recipe/session"; +// highlight-end +import { useHistory } from "react-router-dom5"; - - +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + Passwordless.init({ + contactMethod: "EMAIL", // This example will work with any contactMethod + // ... + }), + // ... + ] +}); + +function AuthPopup() { + let sessionContext = Session.useSessionContext(); + const history = useHistory(); + const [isModalOpen, setIsModalOpen] = useState(false); + + const openModal = () => setIsModalOpen(true); + const closeModal = () => setIsModalOpen(false); + + useEffect(() => { + if (sessionContext.loading) { + return; + } + if (sessionContext.doesSessionExist) { + closeModal(); + } else { + openModal(); + } + }, [sessionContext]); + + if (sessionContext.loading) { + return null; + } + + return ( +
+ {sessionContext.doesSessionExist && ( + // We wrap this with so that + // all claims are validated before showing the logged in UI. + // For example, if email verification is switched on, and + // the user's email is not verified, then + // will redirect to the email verification page. + +

You are logged In!

+

UserId: {sessionContext.userId}

+ +
+ )} + + + {/* highlight-next-line */} + + +
+ ); +} +``` + +
+ + + + + ```tsx +import React, { useState, useEffect } from "react"; +import Modal from "react-modal"; import SuperTokens from "supertokens-auth-react"; import Passwordless from "supertokens-auth-react/recipe/passwordless"; +// highlight-start +import { SignInUp } from 'supertokens-auth-react/recipe/passwordless/prebuiltui'; +import Session from "supertokens-auth-react/recipe/session"; +// highlight-end SuperTokens.init({ appInfo: { @@ -270,30 +676,70 @@ SuperTokens.init({ }, recipeList: [ Passwordless.init({ - contactMethod: "EMAIL_OR_PHONE", // This example will work with any contactMethod. - //highlight-start - getRedirectionURL: async (context) => { - // Prevent redirection after successful sign in/up by returning null. - if (context.action === "SUCCESS") { - return null; - }; - }, - //highlight-end - }) - ], -}) + contactMethod: "EMAIL", // This example will work with any contactMethod + // ... + }), + // ... + ] +}); + +function AuthPopup() { + let sessionContext = Session.useSessionContext(); + const [isModalOpen, setIsModalOpen] = useState(false); + + const openModal = () => setIsModalOpen(true); + const closeModal = () => setIsModalOpen(false); + + useEffect(() => { + if (sessionContext.loading) { + return; + } + if (sessionContext.doesSessionExist) { + closeModal(); + } else { + openModal(); + } + }, [sessionContext]); + + if (sessionContext.loading) { + return null; + } + + return ( +
+ {sessionContext.doesSessionExist && ( + // We wrap this with so that + // all claims are validated before showing the logged in UI. + // For example, if email verification is switched on, and + // the user's email is not verified, then + // will redirect to the email verification page. + +

You are logged In!

+

UserId: {sessionContext.userId}

+ +
+ )} + + + {/* highlight-next-line */} + + +
+ ); +} ``` +
+
:::note -To avoid redirection for failed claims, such as Email Verification, reach out to us on [Discord](https://supertokens.com/discord) for assistance. +In the above case, redirection may occur if a claim fails. For instance, in the case of an Email Verification claim, if the user's email is not verified, they will be redirected to the email verification page. To prevent redirection for failed claims, please contact us on [Discord](https://supertokens.com/discord) for assistance. ::: -## Optional: Rendering Auth components together in a popup and page - -You may choose to display the Auth UI in a full page and in a popup in the same app. For the full-page Auth UI, redirection after a successful login is preferred, whereas in the popup, it is not. In this scenario, you have the option to check either the current URL or the `userContext` object in `getRedirectionURL` to decide whether to return null or not. -
diff --git a/v2/src/plugins/codeTypeChecking/jsEnv/package.json b/v2/src/plugins/codeTypeChecking/jsEnv/package.json index acda50e88..7d2f2f302 100644 --- a/v2/src/plugins/codeTypeChecking/jsEnv/package.json +++ b/v2/src/plugins/codeTypeChecking/jsEnv/package.json @@ -34,6 +34,7 @@ "@types/koa-router": "^7.4.4", "@types/loopback": "^3.2.10", "@types/react-dom": "^18.0.5", + "@types/react-modal": "^3.16.3", "@types/react-router-dom": "^5.3.3", "@types/react-router-dom5": "npm:@types/react-router-dom@^5.3.3", "aws-lambda": "^1.0.7", @@ -49,6 +50,7 @@ "loopback": "^3.28.0", "next": "^13.5.6", "nextjs-cors": "^2.1.0", + "react-modal": "^3.16.1", "react-router-dom": "^6.2.1", "react-router-dom5": "npm:react-router-dom@^5.3.0", "socket.io": "^4.6.1", diff --git a/v2/thirdparty/common-customizations/embed-sign-in-up-form.mdx b/v2/thirdparty/common-customizations/embed-sign-in-up-form.mdx index 0e8f1e580..8b870a52e 100644 --- a/v2/thirdparty/common-customizations/embed-sign-in-up-form.mdx +++ b/v2/thirdparty/common-customizations/embed-sign-in-up-form.mdx @@ -16,16 +16,32 @@ import RRDVersionSubTabs from "/src/components/tabs/RRDVersionSubTabs" -## Step 1: Disable default implementation +## Case 1: Rendering the Auth Widget in a page -This will prevent SuperTokens from displaying the default login UI in the `/auth` page. +The following example shows the scenario where you have a dedicated route, such as `/auth`, for rendering the Auth Widget. Upon a successful login, the user will be automatically redirected to the return value of `getRedirectionURL` (defaulting to `/`). + + + + + + ```tsx +import React from "react"; import SuperTokens from "supertokens-auth-react"; import ThirdParty from "supertokens-auth-react/recipe/thirdparty"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdparty/prebuiltui'; +// highlight-end +// @ts-ignore +import Header from "./header"; +// @ts-ignore +import Footer from "./footer"; +import { useNavigate } from "react-router-dom"; SuperTokens.init({ appInfo: { @@ -37,23 +53,188 @@ SuperTokens.init({ ThirdParty.init({ signInAndUpFeature: { // highlight-next-line - disableDefaultUI: true, - // ... + disableDefaultUI: true, // This will prevent SuperTokens from displaying the default login UI in the `/auth` page. }, + // highlight-start + async getRedirectionURL(context) { + if (context.action === "SUCCESS") { + return "/dashboard"; // defaults to "/" + }; + }, + // highlight-end // ... }), // ... - ] + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +function AuthPage() { + const navigate = useNavigate(); + return ( +
+
+ // highlight-next-line + +
+
+ ); +} +``` + +
+ + + +```tsx +import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import ThirdParty from "supertokens-auth-react/recipe/thirdparty"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdparty/prebuiltui'; +// highlight-end +// @ts-ignore +import Header from "./header"; +// @ts-ignore +import Footer from "./footer"; +import { useHistory } from "react-router-dom5"; + +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + ThirdParty.init({ + signInAndUpFeature: { + // highlight-next-line + disableDefaultUI: true, // This will prevent SuperTokens from displaying the default login UI in the `/auth` page. + }, + // highlight-start + async getRedirectionURL(context) { + if (context.action === "SUCCESS") { + return "/dashboard"; // defaults to "/" + }; + }, + // highlight-end + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end }); + +function AuthPage() { + const history = useHistory(); + return ( +
+
+ // highlight-next-line + +
+
+ ); +} ``` + +
+ +
+ +
+ + +```tsx +import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import ThirdParty from "supertokens-auth-react/recipe/thirdparty"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdparty/prebuiltui'; +// highlight-end +// @ts-ignore +import Header from "./header"; +// @ts-ignore +import Footer from "./footer"; + +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + ThirdParty.init({ + signInAndUpFeature: { + // highlight-next-line + disableDefaultUI: true, // This will prevent SuperTokens from displaying the default login UI in the `/auth` page. + }, + // highlight-start + async getRedirectionURL(context) { + if (context.action === "SUCCESS") { + return "/dashboard"; // defaults to "/" + }; + }, + // highlight-end + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +function AuthPage() { + return ( +
+
+ // highlight-next-line + +
+
+ ) +} +``` +
+
-If you navigate to `/auth`, you should not see the widget anymore. +In the above code snippet, we: + +1. Disabled the default Auth UI by setting `disableDefaultUI` to `true` inside the ThirdParty recipe config. +2. Overrode the `getRedirectionURL` function inside the ThirdParty recipe config to redirect to `/dashboard` upon successful login. +3. Overrode the `getRedirectionURL` function inside the SuperTokens config to redirect to `/auth` when login is required. + +Feel free to customize the redirection URLs as needed. + +:::note +When the user visits the `/auth` page, they will see the SignIn UI by default. To render the SignUp UI, append `show=signup` as a query parameter to the URL, like`/auth?show=signup`. +::: -## Step 2: Render the component yourself +## Case 2: Rendering the Auth Widget in a page with no redirection -For example if you would like to show the login form in our own component which renders custom UI around it, and is shown only if the user is logged in, then we can: +The following example shows the scenario where you have a dedicated route, such as `/auth`, for rendering the Auth Widget. However, upon a successful login, the user will see a logged in UI instead of getting redirected. @@ -67,6 +248,8 @@ For example if you would like to show the login form in our own component which ```tsx import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import ThirdParty from "supertokens-auth-react/recipe/thirdparty"; // highlight-start import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdparty/prebuiltui'; import Session from "supertokens-auth-react/recipe/session"; @@ -77,7 +260,30 @@ import Header from "./header"; import Footer from "./footer"; import { useNavigate } from "react-router-dom"; -function MyLandingPage() { +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + ThirdParty.init({ + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +// highlight-start +function LandingPage() { let sessionContext = Session.useSessionContext(); const navigate = useNavigate(); if (sessionContext.loading) { @@ -107,6 +313,7 @@ function MyLandingPage() { ) } } +// highlight-end ``` @@ -115,6 +322,8 @@ function MyLandingPage() { ```tsx import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import ThirdParty from "supertokens-auth-react/recipe/thirdparty"; // highlight-start import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdparty/prebuiltui'; import Session from "supertokens-auth-react/recipe/session"; @@ -125,7 +334,30 @@ import Header from "./header"; import Footer from "./footer"; import { useHistory } from "react-router-dom5"; -function MyLandingPage() { +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + ThirdParty.init({ + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +// highlight-start +function LandingPage() { let sessionContext = Session.useSessionContext(); const history = useHistory(); if (sessionContext.loading) { @@ -155,6 +387,7 @@ function MyLandingPage() { ) } } +// highlight-end ``` @@ -166,6 +399,8 @@ function MyLandingPage() { ```tsx import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import ThirdParty from "supertokens-auth-react/recipe/thirdparty"; // highlight-start import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdparty/prebuiltui'; import Session from "supertokens-auth-react/recipe/session"; @@ -175,7 +410,30 @@ import Header from "./header"; // @ts-ignore import Footer from "./footer"; -function MyLandingPage() { +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + ThirdParty.init({ + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +// highlight-start +function LandingPage() { let sessionContext = Session.useSessionContext(); if (sessionContext.loading) { return null; @@ -204,57 +462,203 @@ function MyLandingPage() { ) } } +// highlight-end ``` -## Step 3: Changing the website path for the login UI +In the above code snippet, we wrap the logged-in component with `Session.SessionAuth` to validate all claims before displaying the logged-in UI. For instance, with email verification enabled, if a user's email is unverified, `Session.SessionAuth` redirects to the email verification page. -The default path for this is component is `/{websiteBasePath}/`. +:::note +In the above case, redirection may occur if a claim fails. For instance, in the case of an Email Verification claim, if the user's email is not verified, they will be redirected to the email verification page. To prevent redirection for failed claims, please contact us on [Discord](https://supertokens.com/discord) for assistance. +::: -If you are displaying this at some custom path, then you need add additional config on frontend: +## Case 3: Rendering the Auth Widget in a popup + +The following example shows the scenario where you embed the Auth Widget in a popup, and upon successful login, you aim to close the popup. + + + + + + ```tsx +import React, { useState, useEffect } from "react"; +import Modal from "react-modal"; import SuperTokens from "supertokens-auth-react"; import ThirdParty from "supertokens-auth-react/recipe/thirdparty"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdparty/prebuiltui'; +import Session from "supertokens-auth-react/recipe/session"; +// highlight-end +import { useNavigate } from "react-router-dom"; SuperTokens.init({ appInfo: { apiDomain: "...", appName: "...", - websiteDomain: "...", + websiteDomain: "..." }, recipeList: [ - ThirdParty.init({}), - ], - //highlight-start - // The user will be taken to the custom path when then need to login. - getRedirectionURL: async (context) => { - if (context.action === "TO_AUTH") { - return "/custom-login-path"; - }; + ThirdParty.init({ + // ... + }), + // ... + ] +}); + +function AuthPopup() { + let sessionContext = Session.useSessionContext(); + const navigate = useNavigate(); + const [isModalOpen, setIsModalOpen] = useState(false); + + const openModal = () => setIsModalOpen(true); + const closeModal = () => setIsModalOpen(false); + + useEffect(() => { + if (sessionContext.loading) { + return; + } + if (sessionContext.doesSessionExist) { + closeModal(); + } else { + openModal(); } - //highlight-end -}) + }, [sessionContext]); + + if (sessionContext.loading) { + return null; + } + + return ( +
+ {sessionContext.doesSessionExist && ( + // We wrap this with so that + // all claims are validated before showing the logged in UI. + // For example, if email verification is switched on, and + // the user's email is not verified, then + // will redirect to the email verification page. + +

You are logged In!

+

UserId: {sessionContext.userId}

+ +
+ )} + + + {/* highlight-next-line */} + + +
+ ); +} ``` +
-
-## Optional: Prevent redirection after SignIn / Up + + +```tsx +import React, { useState, useEffect } from "react"; +import Modal from "react-modal"; +import SuperTokens from "supertokens-auth-react"; +import ThirdParty from "supertokens-auth-react/recipe/thirdparty"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdparty/prebuiltui'; +import Session from "supertokens-auth-react/recipe/session"; +// highlight-end +import { useHistory } from "react-router-dom5"; + +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + ThirdParty.init({ + // ... + }), + // ... + ] +}); -Upon successful login, SuperTokens redirects the user to the return value of `getRedirectionURL` provided in the recipe config. By default or when returning `undefined` from `getRedirectionURL`, the user is redirected to the `/` route. If you wish to completely prevent redirection, return `null` instead. Typically, this is used if you want to embed the sign in / up component in a popup and want to just dismiss the popup post login. +function AuthPopup() { + let sessionContext = Session.useSessionContext(); + const history = useHistory(); + const [isModalOpen, setIsModalOpen] = useState(false); - - + const openModal = () => setIsModalOpen(true); + const closeModal = () => setIsModalOpen(false); + + useEffect(() => { + if (sessionContext.loading) { + return; + } + if (sessionContext.doesSessionExist) { + closeModal(); + } else { + openModal(); + } + }, [sessionContext]); + + if (sessionContext.loading) { + return null; + } + + return ( +
+ {sessionContext.doesSessionExist && ( + // We wrap this with so that + // all claims are validated before showing the logged in UI. + // For example, if email verification is switched on, and + // the user's email is not verified, then + // will redirect to the email verification page. + +

You are logged In!

+

UserId: {sessionContext.userId}

+ +
+ )} + + + {/* highlight-next-line */} + + +
+ ); +} +``` + +
+ + + + + ```tsx +import React, { useState, useEffect } from "react"; +import Modal from "react-modal"; import SuperTokens from "supertokens-auth-react"; import ThirdParty from "supertokens-auth-react/recipe/thirdparty"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdparty/prebuiltui'; +import Session from "supertokens-auth-react/recipe/session"; +// highlight-end SuperTokens.init({ appInfo: { @@ -264,29 +668,69 @@ SuperTokens.init({ }, recipeList: [ ThirdParty.init({ - //highlight-start - getRedirectionURL: async (context) => { - // Prevent redirection after successful sign in/up by returning null. - if (context.action === "SUCCESS") { - return null; - }; - }, - //highlight-end - }) - ], -}) + // ... + }), + // ... + ] +}); + +function AuthPopup() { + let sessionContext = Session.useSessionContext(); + const [isModalOpen, setIsModalOpen] = useState(false); + + const openModal = () => setIsModalOpen(true); + const closeModal = () => setIsModalOpen(false); + + useEffect(() => { + if (sessionContext.loading) { + return; + } + if (sessionContext.doesSessionExist) { + closeModal(); + } else { + openModal(); + } + }, [sessionContext]); + + if (sessionContext.loading) { + return null; + } + + return ( +
+ {sessionContext.doesSessionExist && ( + // We wrap this with so that + // all claims are validated before showing the logged in UI. + // For example, if email verification is switched on, and + // the user's email is not verified, then + // will redirect to the email verification page. + +

You are logged In!

+

UserId: {sessionContext.userId}

+ +
+ )} + + + {/* highlight-next-line */} + + +
+ ); +} ``` +
+
:::note -To avoid redirection for failed claims, such as Email Verification, reach out to us on [Discord](https://supertokens.com/discord) for assistance. +In the above case, redirection may occur if a claim fails. For instance, in the case of an Email Verification claim, if the user's email is not verified, they will be redirected to the email verification page. To prevent redirection for failed claims, please contact us on [Discord](https://supertokens.com/discord) for assistance. ::: -## Optional: Rendering Auth components together in a popup and page - -You may choose to display the Auth UI in a full page and in a popup in the same app. For the full-page Auth UI, redirection after a successful login is preferred, whereas in the popup, it is not. In this scenario, you have the option to check either the current URL or the `userContext` object in `getRedirectionURL` to decide whether to return null or not. -
diff --git a/v2/thirdpartyemailpassword/common-customizations/embed-sign-in-up-form.mdx b/v2/thirdpartyemailpassword/common-customizations/embed-sign-in-up-form.mdx index 85138fa84..5f08dd844 100644 --- a/v2/thirdpartyemailpassword/common-customizations/embed-sign-in-up-form.mdx +++ b/v2/thirdpartyemailpassword/common-customizations/embed-sign-in-up-form.mdx @@ -16,16 +16,32 @@ import RRDVersionSubTabs from "/src/components/tabs/RRDVersionSubTabs" -## Step 1: Disable default implementation +## Case 1: Rendering the Auth Widget in a page -This will prevent SuperTokens from displaying the default login UI in the `/auth` page. +The following example shows the scenario where you have a dedicated route, such as `/auth`, for rendering the Auth Widget. Upon a successful login, the user will be automatically redirected to the return value of `getRedirectionURL` (defaulting to `/`). + + + + + + ```tsx +import React from "react"; import SuperTokens from "supertokens-auth-react"; import ThirdPartyEmailPassword from "supertokens-auth-react/recipe/thirdpartyemailpassword"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui'; +// highlight-end +// @ts-ignore +import Header from "./header"; +// @ts-ignore +import Footer from "./footer"; +import { useNavigate } from "react-router-dom"; SuperTokens.init({ appInfo: { @@ -37,23 +53,188 @@ SuperTokens.init({ ThirdPartyEmailPassword.init({ signInAndUpFeature: { // highlight-next-line - disableDefaultUI: true, - // ... + disableDefaultUI: true, // This will prevent SuperTokens from displaying the default login UI in the `/auth` page. + }, + // highlight-start + async getRedirectionURL(context) { + if (context.action === "SUCCESS") { + return "/dashboard"; // defaults to "/" + }; }, + // highlight-end // ... }), // ... - ] + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +function AuthPage() { + const navigate = useNavigate(); + return ( +
+
+ // highlight-next-line + +
+
+ ); +} +``` + +
+ + + +```tsx +import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import ThirdPartyEmailPassword from "supertokens-auth-react/recipe/thirdpartyemailpassword"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui'; +// highlight-end +// @ts-ignore +import Header from "./header"; +// @ts-ignore +import Footer from "./footer"; +import { useHistory } from "react-router-dom5"; + +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + ThirdPartyEmailPassword.init({ + signInAndUpFeature: { + // highlight-next-line + disableDefaultUI: true, // This will prevent SuperTokens from displaying the default login UI in the `/auth` page. + }, + // highlight-start + async getRedirectionURL(context) { + if (context.action === "SUCCESS") { + return "/dashboard"; // defaults to "/" + }; + }, + // highlight-end + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +function AuthPage() { + const history = useHistory(); + return ( +
+
+ // highlight-next-line + +
+
+ ); +} +``` + +
+ +
+ +
+ + +```tsx +import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import ThirdPartyEmailPassword from "supertokens-auth-react/recipe/thirdpartyemailpassword"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui'; +// highlight-end +// @ts-ignore +import Header from "./header"; +// @ts-ignore +import Footer from "./footer"; + +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + ThirdPartyEmailPassword.init({ + signInAndUpFeature: { + // highlight-next-line + disableDefaultUI: true, // This will prevent SuperTokens from displaying the default login UI in the `/auth` page. + }, + // highlight-start + async getRedirectionURL(context) { + if (context.action === "SUCCESS") { + return "/dashboard"; // defaults to "/" + }; + }, + // highlight-end + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end }); + +function AuthPage() { + return ( +
+
+ // highlight-next-line + +
+
+ ) +} ``` +
+
-If you navigate to `/auth`, you should not see the widget anymore. +In the above code snippet, we: + +1. Disabled the default Auth UI by setting `disableDefaultUI` to `true` inside the ThirdPartyEmailPassword recipe config. +2. Overrode the `getRedirectionURL` function inside the ThirdPartyEmailPassword recipe config to redirect to `/dashboard` upon successful login. +3. Overrode the `getRedirectionURL` function inside the SuperTokens config to redirect to `/auth` when login is required. -## Step 2: Render the component yourself +Feel free to customize the redirection URLs as needed. -For example if you would like to show the login form in our own component which renders custom UI around it, and is shown only if the user is logged in, then we can: +:::note +When the user visits the `/auth` page, they will see the SignIn UI by default. To render the SignUp UI, append `show=signup` as a query parameter to the URL, like`/auth?show=signup`. +::: + +## Case 2: Rendering the Auth Widget in a page with no redirection + +The following example shows the scenario where you have a dedicated route, such as `/auth`, for rendering the Auth Widget. However, upon a successful login, the user will see a logged in UI instead of getting redirected. @@ -67,6 +248,8 @@ For example if you would like to show the login form in our own component which ```tsx import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import ThirdPartyEmailPassword from "supertokens-auth-react/recipe/thirdpartyemailpassword"; // highlight-start import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui'; import Session from "supertokens-auth-react/recipe/session"; @@ -77,7 +260,30 @@ import Header from "./header"; import Footer from "./footer"; import { useNavigate } from "react-router-dom"; -function MyLandingPage() { +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + ThirdPartyEmailPassword.init({ + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +// highlight-start +function LandingPage() { let sessionContext = Session.useSessionContext(); const navigate = useNavigate(); if (sessionContext.loading) { @@ -107,6 +313,7 @@ function MyLandingPage() { ) } } +// highlight-end ``` @@ -115,6 +322,8 @@ function MyLandingPage() { ```tsx import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import ThirdPartyEmailPassword from "supertokens-auth-react/recipe/thirdpartyemailpassword"; // highlight-start import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui'; import Session from "supertokens-auth-react/recipe/session"; @@ -125,7 +334,30 @@ import Header from "./header"; import Footer from "./footer"; import { useHistory } from "react-router-dom5"; -function MyLandingPage() { +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + ThirdPartyEmailPassword.init({ + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +// highlight-start +function LandingPage() { let sessionContext = Session.useSessionContext(); const history = useHistory(); if (sessionContext.loading) { @@ -155,6 +387,7 @@ function MyLandingPage() { ) } } +// highlight-end ``` @@ -166,6 +399,8 @@ function MyLandingPage() { ```tsx import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import ThirdPartyEmailPassword from "supertokens-auth-react/recipe/thirdpartyemailpassword"; // highlight-start import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui'; import Session from "supertokens-auth-react/recipe/session"; @@ -175,7 +410,30 @@ import Header from "./header"; // @ts-ignore import Footer from "./footer"; -function MyLandingPage() { +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + ThirdPartyEmailPassword.init({ + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +// highlight-start +function LandingPage() { let sessionContext = Session.useSessionContext(); if (sessionContext.loading) { return null; @@ -204,59 +462,203 @@ function MyLandingPage() { ) } } +// highlight-end ``` -## Step 3: Changing the website path for the login UI +In the above code snippet, we wrap the logged-in component with `Session.SessionAuth` to validate all claims before displaying the logged-in UI. For instance, with email verification enabled, if a user's email is unverified, `Session.SessionAuth` redirects to the email verification page. -The default path for this is component is `/{websiteBasePath}/`. +:::note +In the above case, redirection may occur if a claim fails. For instance, in the case of an Email Verification claim, if the user's email is not verified, they will be redirected to the email verification page. To prevent redirection for failed claims, please contact us on [Discord](https://supertokens.com/discord) for assistance. +::: -If you are displaying this at some custom path, then you need add additional config on frontend: +## Case 3: Rendering the Auth Widget in a popup + +The following example shows the scenario where you embed the Auth Widget in a popup, and upon successful login, you aim to close the popup. + + + + + + ```tsx +import React, { useState, useEffect } from "react"; +import Modal from "react-modal"; import SuperTokens from "supertokens-auth-react"; import ThirdPartyEmailPassword from "supertokens-auth-react/recipe/thirdpartyemailpassword"; +// highlight-start +import { SignInAndUp } from "supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui"; +import Session from "supertokens-auth-react/recipe/session"; +// highlight-end +import { useNavigate } from "react-router-dom"; SuperTokens.init({ appInfo: { apiDomain: "...", appName: "...", - websiteDomain: "...", + websiteDomain: "..." }, recipeList: [ ThirdPartyEmailPassword.init({ // ... }), - ], - //highlight-start - // The user will be taken to the custom path when then need to login. - getRedirectionURL: async (context) => { - if (context.action === "TO_AUTH") { - return "/custom-login-path"; - }; + // ... + ] +}); + +function AuthPopup() { + let sessionContext = Session.useSessionContext(); + const navigate = useNavigate(); + const [isModalOpen, setIsModalOpen] = useState(false); + + const openModal = () => setIsModalOpen(true); + const closeModal = () => setIsModalOpen(false); + + useEffect(() => { + if (sessionContext.loading) { + return; + } + if (sessionContext.doesSessionExist) { + closeModal(); + } else { + openModal(); } - //highlight-end -}) + }, [sessionContext]); + + if (sessionContext.loading) { + return null; + } + + return ( +
+ {sessionContext.doesSessionExist && ( + // We wrap this with so that + // all claims are validated before showing the logged in UI. + // For example, if email verification is switched on, and + // the user's email is not verified, then + // will redirect to the email verification page. + +

You are logged In!

+

UserId: {sessionContext.userId}

+ +
+ )} + + + {/* highlight-next-line */} + + +
+ ); +} ``` +
-
-## Optional: Prevent redirection after SignIn / Up + -Upon successful login, SuperTokens redirects the user to the return value of `getRedirectionURL` provided in the recipe config. By default or when returning `undefined` from `getRedirectionURL`, the user is redirected to the `/` route. If you wish to completely prevent redirection, return `null` instead. Typically, this is used if you want to embed the sign in / up component in a popup and want to just dismiss the popup post login. +```tsx +import React, { useState, useEffect } from "react"; +import Modal from "react-modal"; +import SuperTokens from "supertokens-auth-react"; +import ThirdPartyEmailPassword from "supertokens-auth-react/recipe/thirdpartyemailpassword"; +// highlight-start +import { SignInAndUp } from "supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui"; +import Session from "supertokens-auth-react/recipe/session"; +// highlight-end +import { useHistory } from "react-router-dom5"; - - +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + ThirdPartyEmailPassword.init({ + // ... + }), + // ... + ] +}); + +function AuthPopup() { + let sessionContext = Session.useSessionContext(); + const history = useHistory(); + const [isModalOpen, setIsModalOpen] = useState(false); + + const openModal = () => setIsModalOpen(true); + const closeModal = () => setIsModalOpen(false); + + useEffect(() => { + if (sessionContext.loading) { + return; + } + if (sessionContext.doesSessionExist) { + closeModal(); + } else { + openModal(); + } + }, [sessionContext]); + + if (sessionContext.loading) { + return null; + } + + return ( +
+ {sessionContext.doesSessionExist && ( + // We wrap this with so that + // all claims are validated before showing the logged in UI. + // For example, if email verification is switched on, and + // the user's email is not verified, then + // will redirect to the email verification page. + +

You are logged In!

+

UserId: {sessionContext.userId}

+ +
+ )} + + + {/* highlight-next-line */} + + +
+ ); +} +``` + +
+ + + + + ```tsx +import React, { useState, useEffect } from "react"; +import Modal from "react-modal"; import SuperTokens from "supertokens-auth-react"; import ThirdPartyEmailPassword from "supertokens-auth-react/recipe/thirdpartyemailpassword"; +// highlight-start +import { SignInAndUp } from "supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui"; +import Session from "supertokens-auth-react/recipe/session"; +// highlight-end SuperTokens.init({ appInfo: { @@ -266,29 +668,69 @@ SuperTokens.init({ }, recipeList: [ ThirdPartyEmailPassword.init({ - //highlight-start - getRedirectionURL: async (context) => { - // Prevent redirection after successful sign in/up by returning null. - if (context.action === "SUCCESS") { - return null; - }; - }, - //highlight-end - }) - ], -}) + // ... + }), + // ... + ] +}); + +function AuthPopup() { + let sessionContext = Session.useSessionContext(); + const [isModalOpen, setIsModalOpen] = useState(false); + + const openModal = () => setIsModalOpen(true); + const closeModal = () => setIsModalOpen(false); + + useEffect(() => { + if (sessionContext.loading) { + return; + } + if (sessionContext.doesSessionExist) { + closeModal(); + } else { + openModal(); + } + }, [sessionContext]); + + if (sessionContext.loading) { + return null; + } + + return ( +
+ {sessionContext.doesSessionExist && ( + // We wrap this with so that + // all claims are validated before showing the logged in UI. + // For example, if email verification is switched on, and + // the user's email is not verified, then + // will redirect to the email verification page. + +

You are logged In!

+

UserId: {sessionContext.userId}

+ +
+ )} + + + {/* highlight-next-line */} + + +
+ ); +} ``` +
+
:::note -To avoid redirection for failed claims, such as Email Verification, reach out to us on [Discord](https://supertokens.com/discord) for assistance. +In the above case, redirection may occur if a claim fails. For instance, in the case of an Email Verification claim, if the user's email is not verified, they will be redirected to the email verification page. To prevent redirection for failed claims, please contact us on [Discord](https://supertokens.com/discord) for assistance. ::: -## Optional: Rendering Auth components together in a popup and page - -You may choose to display the Auth UI in a full page and in a popup in the same app. For the full-page Auth UI, redirection after a successful login is preferred, whereas in the popup, it is not. In this scenario, you have the option to check either the current URL or the `userContext` object in `getRedirectionURL` to decide whether to return null or not. -
diff --git a/v2/thirdpartypasswordless/common-customizations/embed-sign-in-up-form.mdx b/v2/thirdpartypasswordless/common-customizations/embed-sign-in-up-form.mdx index 04b1ff585..eb0066796 100644 --- a/v2/thirdpartypasswordless/common-customizations/embed-sign-in-up-form.mdx +++ b/v2/thirdpartypasswordless/common-customizations/embed-sign-in-up-form.mdx @@ -16,16 +16,32 @@ import RRDVersionSubTabs from "/src/components/tabs/RRDVersionSubTabs" -## Step 1: Disable default implementation +## Case 1: Rendering the Auth Widget in a page -This will prevent SuperTokens from displaying the default login UI in the `/auth` page. +The following example shows the scenario where you have a dedicated route, such as `/auth`, for rendering the Auth Widget. Upon a successful login, the user will be automatically redirected to the return value of `getRedirectionURL` (defaulting to `/`). + + + + + + ```tsx +import React from "react"; import SuperTokens from "supertokens-auth-react"; import ThirdPartyPasswordless from "supertokens-auth-react/recipe/thirdpartypasswordless"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdpartypasswordless/prebuiltui'; +// highlight-end +// @ts-ignore +import Header from "./header"; +// @ts-ignore +import Footer from "./footer"; +import { useNavigate } from "react-router-dom"; SuperTokens.init({ appInfo: { @@ -38,24 +54,190 @@ SuperTokens.init({ contactMethod: "EMAIL", // This example will work with any contactMethod signInUpFeature: { // highlight-next-line - disableDefaultUI: true, - // ... + disableDefaultUI: true, // This will prevent SuperTokens from displaying the default login UI in the `/auth` page. }, + // highlight-start + async getRedirectionURL(context) { + if (context.action === "SUCCESS") { + return "/dashboard"; // defaults to "/" + }; + }, + // highlight-end // ... }), // ... - ] + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end }); + +function AuthPage() { + const navigate = useNavigate(); + return ( +
+
+ // highlight-next-line + +
+
+ ); +} ``` -If you navigate to `/auth`, you should not see the widget anymore. +
+ + + +```tsx +import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import ThirdPartyPasswordless from "supertokens-auth-react/recipe/thirdpartypasswordless"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdpartypasswordless/prebuiltui'; +// highlight-end +// @ts-ignore +import Header from "./header"; +// @ts-ignore +import Footer from "./footer"; +import { useHistory } from "react-router-dom5"; + +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + ThirdPartyPasswordless.init({ + contactMethod: "EMAIL", // This example will work with any contactMethod + signInUpFeature: { + // highlight-next-line + disableDefaultUI: true, // This will prevent SuperTokens from displaying the default login UI in the `/auth` page. + }, + // highlight-start + async getRedirectionURL(context) { + if (context.action === "SUCCESS") { + return "/dashboard"; // defaults to "/" + }; + }, + // highlight-end + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +function AuthPage() { + const history = useHistory(); + return ( +
+
+ // highlight-next-line + +
+
+ ); +} +``` + +
+ +
+ +
+ + +```tsx +import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import ThirdPartyPasswordless from "supertokens-auth-react/recipe/thirdpartypasswordless"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdpartypasswordless/prebuiltui'; +// highlight-end +// @ts-ignore +import Header from "./header"; +// @ts-ignore +import Footer from "./footer"; + +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + ThirdPartyPasswordless.init({ + contactMethod: "EMAIL", // This example will work with any contactMethod + signInUpFeature: { + // highlight-next-line + disableDefaultUI: true, // This will prevent SuperTokens from displaying the default login UI in the `/auth` page. + }, + // highlight-start + async getRedirectionURL(context) { + if (context.action === "SUCCESS") { + return "/dashboard"; // defaults to "/" + }; + }, + // highlight-end + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); +function AuthPage() { + return ( +
+
+ // highlight-next-line + +
+
+ ) +} +``` +
+
-## Step 2: Render the component yourself +In the above code snippet, we: + +1. Disabled the default Auth UI by setting `disableDefaultUI` to `true` inside the ThirdPartyPasswordless recipe config. +2. Overrode the `getRedirectionURL` function inside the ThirdPartyPasswordless recipe config to redirect to `/dashboard` upon successful login. +3. Overrode the `getRedirectionURL` function inside the SuperTokens config to redirect to `/auth` when login is required. -For example if you would like to show the login form in our own component which renders custom UI around it, and is shown only if the user is logged in, then we can: +Feel free to customize the redirection URLs as needed. + +:::note +When the user visits the `/auth` page, they will see the SignIn UI by default. To render the SignUp UI, append `show=signup` as a query parameter to the URL, like`/auth?show=signup`. +::: + +## Case 2: Rendering the Auth Widget in a page with no redirection + +The following example shows the scenario where you have a dedicated route, such as `/auth`, for rendering the Auth Widget. However, upon a successful login, the user will see a logged in UI instead of getting redirected. @@ -69,6 +251,8 @@ For example if you would like to show the login form in our own component which ```tsx import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import ThirdPartyPasswordless from "supertokens-auth-react/recipe/thirdpartypasswordless"; // highlight-start import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdpartypasswordless/prebuiltui'; import Session from "supertokens-auth-react/recipe/session"; @@ -79,7 +263,31 @@ import Header from "./header"; import Footer from "./footer"; import { useNavigate } from "react-router-dom"; -function MyLandingPage() { +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + ThirdPartyPasswordless.init({ + contactMethod: "EMAIL", // This example will work with any contactMethod + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +// highlight-start +function LandingPage() { let sessionContext = Session.useSessionContext(); const navigate = useNavigate(); if (sessionContext.loading) { @@ -109,6 +317,7 @@ function MyLandingPage() { ) } } +// highlight-end ``` @@ -117,6 +326,8 @@ function MyLandingPage() { ```tsx import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import ThirdPartyPasswordless from "supertokens-auth-react/recipe/thirdpartypasswordless"; // highlight-start import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdpartypasswordless/prebuiltui'; import Session from "supertokens-auth-react/recipe/session"; @@ -127,7 +338,31 @@ import Header from "./header"; import Footer from "./footer"; import { useHistory } from "react-router-dom5"; -function MyLandingPage() { +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + ThirdPartyPasswordless.init({ + contactMethod: "EMAIL", // This example will work with any contactMethod + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +// highlight-start +function LandingPage() { let sessionContext = Session.useSessionContext(); const history = useHistory(); if (sessionContext.loading) { @@ -157,6 +392,7 @@ function MyLandingPage() { ) } } +// highlight-end ``` @@ -166,9 +402,10 @@ function MyLandingPage() { - ```tsx import React from "react"; +import SuperTokens from "supertokens-auth-react"; +import ThirdPartyPasswordless from "supertokens-auth-react/recipe/thirdpartypasswordless"; // highlight-start import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdpartypasswordless/prebuiltui'; import Session from "supertokens-auth-react/recipe/session"; @@ -178,7 +415,31 @@ import Header from "./header"; // @ts-ignore import Footer from "./footer"; -function MyLandingPage() { +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + ThirdPartyPasswordless.init({ + contactMethod: "EMAIL", // This example will work with any contactMethod + // ... + }), + // ... + ], + // highlight-start + async getRedirectionURL(context) { + // The user will be taken to this path when they need to login. + if (context.action === "TO_AUTH") { + return "/auth"; // return the path where you are rendering the Auth UI + }; + }, + // highlight-end +}); + +// highlight-start +function LandingPage() { let sessionContext = Session.useSessionContext(); if (sessionContext.loading) { return null; @@ -207,26 +468,43 @@ function MyLandingPage() { ) } } +// highlight-end ``` - - -## Step 3: Changing the website path for the login UI +In the above code snippet, we wrap the logged-in component with `Session.SessionAuth` to validate all claims before displaying the logged-in UI. For instance, with email verification enabled, if a user's email is unverified, `Session.SessionAuth` redirects to the email verification page. -The default path for this is component is `/{websiteBasePath}/`. +:::note +In the above case, redirection may occur if a claim fails. For instance, in the case of an Email Verification claim, if the user's email is not verified, they will be redirected to the email verification page. To prevent redirection for failed claims, please contact us on [Discord](https://supertokens.com/discord) for assistance. +::: + +## Case 3: Rendering the Auth Widget in a popup -If you are displaying this at some custom path, then you need add additional config on frontend: +The following example shows the scenario where you embed the Auth Widget in a popup, and upon successful login, you aim to close the popup. + + + + + + ```tsx +import React, { useState, useEffect } from "react"; +import Modal from "react-modal"; import SuperTokens from "supertokens-auth-react"; import ThirdPartyPasswordless from "supertokens-auth-react/recipe/thirdpartypasswordless"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdpartypasswordless/prebuiltui'; +import Session from "supertokens-auth-react/recipe/session"; +// highlight-end +import { useNavigate } from "react-router-dom"; SuperTokens.init({ appInfo: { @@ -237,31 +515,158 @@ SuperTokens.init({ recipeList: [ ThirdPartyPasswordless.init({ contactMethod: "EMAIL", // This example will work with any contactMethod - }) - ], - //highlight-start - // The user will be taken to the custom path when then need to login. - getRedirectionURL: async (context) => { - if (context.action === "TO_AUTH") { - return "/custom-login-path"; - }; + // ... + }), + // ... + ] +}); + +function AuthPopup() { + let sessionContext = Session.useSessionContext(); + const navigate = useNavigate(); + const [isModalOpen, setIsModalOpen] = useState(false); + + const openModal = () => setIsModalOpen(true); + const closeModal = () => setIsModalOpen(false); + + useEffect(() => { + if (sessionContext.loading) { + return; + } + if (sessionContext.doesSessionExist) { + closeModal(); + } else { + openModal(); } - //highlight-end -}) + }, [sessionContext]); + + if (sessionContext.loading) { + return null; + } + + return ( +
+ {sessionContext.doesSessionExist && ( + // We wrap this with so that + // all claims are validated before showing the logged in UI. + // For example, if email verification is switched on, and + // the user's email is not verified, then + // will redirect to the email verification page. + +

You are logged In!

+

UserId: {sessionContext.userId}

+ +
+ )} + + + {/* highlight-next-line */} + + +
+ ); +} ``` +
-
-## Optional: Prevent redirection after SignIn / Up + + +```tsx +import React, { useState, useEffect } from "react"; +import Modal from "react-modal"; +import SuperTokens from "supertokens-auth-react"; +import ThirdPartyPasswordless from "supertokens-auth-react/recipe/thirdpartypasswordless"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdpartypasswordless/prebuiltui'; +import Session from "supertokens-auth-react/recipe/session"; +// highlight-end +import { useHistory } from "react-router-dom5"; + +SuperTokens.init({ + appInfo: { + apiDomain: "...", + appName: "...", + websiteDomain: "..." + }, + recipeList: [ + ThirdPartyPasswordless.init({ + contactMethod: "EMAIL", // This example will work with any contactMethod + // ... + }), + // ... + ] +}); + +function AuthPopup() { + let sessionContext = Session.useSessionContext(); + const history = useHistory(); + const [isModalOpen, setIsModalOpen] = useState(false); -Upon successful login, SuperTokens redirects the user to the return value of `getRedirectionURL` provided in the recipe config. By default or when returning `undefined` from `getRedirectionURL`, the user is redirected to the `/` route. If you wish to completely prevent redirection, return `null` instead. Typically, this is used if you want to embed the sign in / up component in a popup and want to just dismiss the popup post login. + const openModal = () => setIsModalOpen(true); + const closeModal = () => setIsModalOpen(false); - - + useEffect(() => { + if (sessionContext.loading) { + return; + } + if (sessionContext.doesSessionExist) { + closeModal(); + } else { + openModal(); + } + }, [sessionContext]); + + if (sessionContext.loading) { + return null; + } + + return ( +
+ {sessionContext.doesSessionExist && ( + // We wrap this with so that + // all claims are validated before showing the logged in UI. + // For example, if email verification is switched on, and + // the user's email is not verified, then + // will redirect to the email verification page. + +

You are logged In!

+

UserId: {sessionContext.userId}

+ +
+ )} + + + {/* highlight-next-line */} + + +
+ ); +} +``` + +
+ + + + + ```tsx +import React, { useState, useEffect } from "react"; +import Modal from "react-modal"; import SuperTokens from "supertokens-auth-react"; import ThirdPartyPasswordless from "supertokens-auth-react/recipe/thirdpartypasswordless"; +// highlight-start +import { SignInAndUp } from 'supertokens-auth-react/recipe/thirdpartypasswordless/prebuiltui'; +import Session from "supertokens-auth-react/recipe/session"; +// highlight-end SuperTokens.init({ appInfo: { @@ -271,30 +676,70 @@ SuperTokens.init({ }, recipeList: [ ThirdPartyPasswordless.init({ - contactMethod: "EMAIL_OR_PHONE", // This example will work with any contactMethod. - //highlight-start - getRedirectionURL: async (context) => { - // Prevent redirection after successful sign in/up by returning null. - if (context.action === "SUCCESS") { - return null; - }; - }, - //highlight-end - }) - ], -}) + contactMethod: "EMAIL", // This example will work with any contactMethod + // ... + }), + // ... + ] +}); + +function AuthPopup() { + let sessionContext = Session.useSessionContext(); + const [isModalOpen, setIsModalOpen] = useState(false); + + const openModal = () => setIsModalOpen(true); + const closeModal = () => setIsModalOpen(false); + + useEffect(() => { + if (sessionContext.loading) { + return; + } + if (sessionContext.doesSessionExist) { + closeModal(); + } else { + openModal(); + } + }, [sessionContext]); + + if (sessionContext.loading) { + return null; + } + + return ( +
+ {sessionContext.doesSessionExist && ( + // We wrap this with so that + // all claims are validated before showing the logged in UI. + // For example, if email verification is switched on, and + // the user's email is not verified, then + // will redirect to the email verification page. + +

You are logged In!

+

UserId: {sessionContext.userId}

+ +
+ )} + + + {/* highlight-next-line */} + + +
+ ); +} ``` +
+
:::note -To avoid redirection for failed claims, such as Email Verification, reach out to us on [Discord](https://supertokens.com/discord) for assistance. +In the above case, redirection may occur if a claim fails. For instance, in the case of an Email Verification claim, if the user's email is not verified, they will be redirected to the email verification page. To prevent redirection for failed claims, please contact us on [Discord](https://supertokens.com/discord) for assistance. ::: -## Optional: Rendering Auth components together in a popup and page - -You may choose to display the Auth UI in a full page and in a popup in the same app. For the full-page Auth UI, redirection after a successful login is preferred, whereas in the popup, it is not. In this scenario, you have the option to check either the current URL or the `userContext` object in `getRedirectionURL` to decide whether to return null or not. -