Hi, I am currently trying to setup ory for my Reac...
# _newcomer
a
Hi, I am currently trying to setup ory for my React SPA using Vite. I have a context file that is wrapping my application. I am running the ory tunnel with
ory tunnel --project <site-id> <http://localhost:5173>
but am experiencing some interesting behaviour. Firstly the redirect consistently takes me to
/ui/welcome
rather than back to
localhost:5173
. I have tried numerous methods for resolving this but nothing consistently works. When I run the ory tunnel and change the base url to
<http://localhost:4000>
it fails to authenticate and send a session token. My page constantly refreshes looking to make a connection. Secondly, I recieve the following error
Property 'logout_url' does not exist on type 'AxiosResponse<LogoutFlow, any>'.
on
const { logout_url } = await ory.createBrowserLogoutFlow();
. To get the type correctly I need to use
Copy code
const logoutFlow = await ory.createBrowserLogoutFlow();
setLogoutUrl(logoutFlow.data.logout_url);
You may want to update your documentation to reflect this. Hoping someone can provide some advice around the best way to resolve my issues. Thanks I have attached below some relevant code snippets
Copy code
import { createContext, useContext, useEffect, useState, type JSX } from "react";
import { Configuration, FrontendApi, type Session } from "@ory/client";

interface AuthContextType {
  session: Session | null;
  logoutUrl: string | null;
  loading: boolean;
  error: string | null;
}

const basePath: string = (import.meta.env.VITE_ORY_SDK_URL);

export const ory = new FrontendApi(
  new Configuration({
    basePath,
    baseOptions: {
      withCredentials: true,
    },
  }),
);

const AuthContext = createContext<AuthContextType>({
  session: null,
  logoutUrl: null,
  loading: true,
  error: null,
});

export const useAuth = (): AuthContextType => useContext(AuthContext);

export const AuthProvider = ({ children }: { children: React.ReactNode }): JSX.Element => {
  const [session, setSession] = useState<Session | null>(null);
  const [logoutUrl, setLogoutUrl] = useState<string | null>(null);
  const [loading, setLoading] = useState<boolean>(true);
  const [error, setError] = useState<string | null>(null);

  const fetchSession = async (): Promise<void> => {
    try {
      setLoading(true);
      setError(null);

      const { data: sessionData } = await ory.toSession();
      console.log("Session data:", sessionData);
      setSession(sessionData);

      try {
        const logoutFlow = await ory.createBrowserLogoutFlow();
        setLogoutUrl(logoutFlow.data.logout_url);
      } catch (logoutError) {
        console.error("Error creating logout flow:", logoutError);
      }
    } catch (err) {
      console.error("Error fetching session:", err);
      window.location.href = basePath + "/self-service/login/browser";
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    fetchSession();
  }, []);

  if (loading) {
    return (
      <div className="flex items-center justify-center min-h-screen">
        <div className="animate-spin rounded-full h-32 w-32 border-b-2 border-gray-900"></div>
      </div>
    );
  }

  if (error) {
    return (
      <div className="flex items-center justify-center min-h-screen">
        <div className="text-center">
          <div className="text-red-600 text-xl mb-4">Authentication Error</div>
          <div className="text-gray-600 mb-4">{error}</div>
          <button
            onClick={() => window.location.reload()}
            className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
          >
            Retry
          </button>
        </div>
      </div>
    );
  }

  return (
    <AuthContext.Provider value={{ session, logoutUrl, loading, error }}>
      {children}
    </AuthContext.Provider>
  );
};

export const ProtectedRoute = ({ children }: { children: React.ReactNode }): JSX.Element => {
  const { session, loading } = useAuth();

  if (loading) {
    return (
      <div className="flex items-center justify-center min-h-screen">
        <div className="animate-spin rounded-full h-32 w-32 border-b-2 border-gray-900"></div>
      </div>
    );
  }

  if (!session) {
    return (
      <div className="flex items-center justify-center min-h-screen">
        <div className="text-center">
          <div className="text-xl mb-4">Please log in to access this page</div>
          <button
            onClick={() => {
              window.location.href = basePath + "/self-service/login/browser";
            }}
            className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
          >
            Go to Login
          </button>
        </div>
      </div>
    );
  }

  return <>{children}</>;
};
And the following is how I am attempting to access the
logout_url
for the location of my log out button
Copy code
const { logoutUrl } = useAuth();

  const handleLogout = (): void => {
    ory
      .createBrowserLogoutFlow()
      .then(({ data }) => {
        if (logoutUrl) {
          window.location.href = data.logout_url;
        } else {
          console.error("Logout URL not available");
        }
      });
  };