Repository: logto-io/logto
File: packages/console/src/pages/OneTimeTokenLanding/index.tsx (TypeScript)

Code before:
function OneTimeTokenLanding() {
  const navigate = useNavigate();
  const { isAuthenticated, signIn, isLoading } = useLogto();
  const [searchParams] = useSearchParams();
  const { navigateTenant, currentTenantId } = useContext(TenantsContext);
  const redirectUri = useRedirectUri();

  useEffect(() => {
    if (isAuthenticated) {
      // If we have a current tenant, navigate to it
      if (currentTenantId) {
        navigateTenant(currentTenantId);
      } else {
        // Otherwise navigate to root, which will handle tenant selection
        navigate('/', { replace: true });
      }
    }
  }, [isAuthenticated, navigate, currentTenantId, navigateTenant]);

  useEffect(() => {
    if (isLoading || isAuthenticated) {
      return;
    }

    const oneTimeToken = searchParams.get(OneTimeTokenLandingSearchParams.OneTimeToken);
    const email = searchParams.get(OneTimeTokenLandingSearchParams.Email);

    if (!oneTimeToken || !email) {
      navigate('/', { replace: true });
      return;
    }

    const handleSignIn = async () => {
      try {
        await signIn({
          redirectUri,
          clearTokens: false,
          extraParams: {
            [ExtraParamsKey.OneTimeToken]: oneTimeToken,
            [ExtraParamsKey.LoginHint]: email,
          },
        });
      } catch {
        navigate('/', { replace: true });
      }
    };

    void handleSignIn();
  }, [searchParams, signIn, isLoading, isAuthenticated, navigate, redirectUri]);

  return <AppLoading />;

Review comment (security):
```suggestion
    if (isLoading) {
      return;
    }

    const oneTimeToken = searchParams.get(OneTimeTokenLandingSearchParams.OneTimeToken);
    const email = searchParams.get(OneTimeTokenLandingSearchParams.Email);

    if (isAuthenticated || !oneTimeToken || !email) {
      navigate('/', { replace: true });
      return;
    }
```
This way, the first `useEffect` could be saved

Code after:
function OneTimeTokenLanding() {
  const navigate = useNavigate();
  const { isAuthenticated, signIn } = useLogto();
  const [searchParams] = useSearchParams();
  const { navigateTenant } = useContext(TenantsContext);
  const redirectUri = useRedirectUri();

  const oneTimeToken = searchParams.get(OneTimeTokenLandingSearchParams.OneTimeToken);
  const email = searchParams.get(OneTimeTokenLandingSearchParams.Email);

  useEffect(() => {
    if (isAuthenticated || !oneTimeToken || !email) {
      // Navigate to root, which will handle tenant selection
      navigate('/', { replace: true });
      return;
    }

    void signIn({
      redirectUri,
      /**
       * Can not clear tokens here since user may already have tokens and let user select which account to keep.
       * We can hence clear tokens in the <Callback /> page.
       */
      clearTokens: false,
      extraParams: {
        [ExtraParamsKey.OneTimeToken]: oneTimeToken,
        [ExtraParamsKey.LoginHint]: email,
      },
    });
  }, [isAuthenticated, navigate, navigateTenant, signIn, redirectUri, oneTimeToken, email]);

  return <AppLoading />;
}

export default OneTimeTokenLanding;