import {OAuthProviders, OTPMethods, Products, StytchEvent, StytchLoginConfig} from "@stytch/vanilla-js"; import {IdentityProvider, StytchLogin, useStytch, useStytchUser} from "@stytch/react"; import {useEffect, useMemo} from "react"; /** * A higher-order component that enforces a login requirement for the wrapped component. * If the user is not logged in, the user is redirected to the login page and the * current URL is stored in localStorage to enable return after authentication. */ export const withLoginRequired = (Component: React.FC) => () => { const {user, fromCache} = useStytchUser() useEffect(() => { if (!user && !fromCache) { localStorage.setItem('returnTo', window.location.href); window.location.href = '/login'; } }, [user, fromCache]) if (!user) { return null } return } /** * The other half of the withLoginRequired flow * Redirects the user to a specified URL stored in local storage or a default location. * Behavior: * - Checks for a `returnTo` entry in local storage to determine the redirection target. * - If `returnTo` exists, clears its value from local storage and navigates to the specified URL. * - If `returnTo` does not exist, redirects the user to the default '/todoapp' location. */ const onLoginComplete = () => { const returnTo = localStorage.getItem('returnTo') if (returnTo) { localStorage.setItem('returnTo', ''); window.location.href = returnTo; } else { window.location.href = '/todoapp'; } } /** * The Login page implementation. Wraps the StytchLogin UI component. * View all configuration options at https://stytch.com/docs/sdks/ui-configuration */ export function Login() { const loginConfig = useMemo(() => ({ products: [Products.otp, Products.oauth], otpOptions: { expirationMinutes: 10, methods: [OTPMethods.Email], }, oauthOptions: { providers: [{type: OAuthProviders.Google}], loginRedirectURL: window.location.origin + '/authenticate', signupRedirectURL: window.location.origin + '/authenticate', } }), []) const handleOnLoginComplete = (evt: StytchEvent) => { if (evt.type !== "AUTHENTICATE_FLOW_COMPLETE") return; onLoginComplete(); } return ( ) } /** * The Authentication callback page implementation. Handles completing the login flow after OAuth */ export function Authenticate() { const client = useStytch(); useEffect(() => { const params = new URLSearchParams(window.location.search); const token = params.get('token'); if (!token) return; client.oauth.authenticate(token, {session_duration_minutes: 60}) .then(onLoginComplete) }, [client]); return ( <> Loading... ) } export const Logout = function () { const stytch = useStytch() const {user} = useStytchUser() if (!user) return null; return ( ) }