Skip to main content
By default, InsForge redirects users to hosted login pages on your backend. If you prefer the entire authentication flow to stay within your app without redirects, you can build custom auth pages using our pre-built components. This guide uses @insforge/react-router as an example. The same components are available in all InsForge packages.

Setup

Step 1: Setup Provider

Wrap your app with InsforgeProvider:
src/main.tsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { InsforgeProvider } from '@insforge/react-router';
import { insforge } from './lib/insforge';
import App from './App';

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <InsforgeProvider client={insforge} afterSignInUrl="/dashboard">
      <App />
    </InsforgeProvider>
  </StrictMode>
);

Step 2: Configure Router with Custom Pages

Set builtInAuth: false and provide your page components:
src/App.tsx
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import { getInsforgeRoutes } from '@insforge/react-router/router';
import Layout from './components/Layout';
import Home from './pages/Home';
import Dashboard from './pages/Dashboard';
// Import your custom auth pages
import SignInPage from './pages/auth/SignInPage';
import SignUpPage from './pages/auth/SignUpPage';
import ForgotPasswordPage from './pages/auth/ForgotPasswordPage';

const router = createBrowserRouter([
  {
    path: '/',
    element: <Layout />,
    children: [
      { index: true, element: <Home /> },
      { path: 'dashboard', element: <Dashboard /> },
    ],
  },

  // Custom auth routes
  ...getInsforgeRoutes({
    baseUrl: import.meta.env.VITE_INSFORGE_BASE_URL || 'https://your-app.region.insforge.app', // Replace with your InsForge backend URL
    afterSignInUrl: '/dashboard',
    builtInAuth: false, // Render custom components instead of redirecting
    pages: {
      signIn: <SignInPage />,
      signUp: <SignUpPage />,
      forgotPassword: <ForgotPasswordPage />,
    },
  }),
]);

export default function App() {
  return <RouterProvider router={router} />;
}

Step 3: Create Auth Page Components

Use our complete authentication components directly. These components are full-featured page-level components with all business logic included:
src/pages/auth/SignInPage.tsx
import { SignIn } from '@insforge/react-router';

export default function SignInPage() {
  return (
    <div className="h-screen flex items-center justify-center">
      <SignIn
        title="Welcome Back"
        subtitle="Sign in to your account"
        onError={(error) => {
          console.error('Sign in error:', error);
        }}
      />
    </div>
  );
}
src/pages/auth/SignUpPage.tsx
import { SignUp } from '@insforge/react-router';

export default function SignUpPage() {
  return (
    <div className="h-screen flex items-center justify-center">
      <SignUp
        title="Create Account"
        subtitle="Get started for free"
        onError={(error) => {
          console.error('Sign up error:', error);
        }}
      />
    </div>
  );
}
src/pages/auth/ForgotPasswordPage.tsx
import { ForgotPassword } from '@insforge/react-router';

export default function ForgotPasswordPage() {
  return (
    <div className="h-screen flex items-center justify-center">
      <ForgotPassword
        onError={(error) => {
          console.error('Password reset error:', error);
        }}
      />
    </div>
  );
}
That’s it! The <SignIn>, <SignUp>, and <ForgotPassword> components are complete page-level components that include:
  • Form UI with validation
  • OAuth provider buttons (auto-detected)
  • Error handling
  • Loading states
  • Password strength indicators (SignUp)
  • All authentication logic
You only need to wrap them in your page components for layout/styling purposes.

Key Difference from Built-in Auth

Built-in Auth:
  • /sign-in → Redirects to https://your-app.region.insforge.app/auth/sign-in
  • Authentication happens on hosted page
  • Returns to your app with token
Custom Components:
  • /sign-in → Renders your <SignInPage> component
  • Authentication happens in your app
  • SDK handles token management automatically

Features

  • Built-in Auth: React Router integration with deployed auth pages
  • Complete Components: Pre-built <SignIn>, <SignUp>, <UserButton> with business logic
  • OAuth Support: Google, GitHub, Discord, Facebook, LinkedIn, Microsoft, Apple, X, Instagram, TikTok, Spotify
  • React Hooks: useAuth(), useUser(), usePublicAuthConfig()
  • Control Components: <SignedIn>, <SignedOut>, <Protect>
  • Form Components: Pure UI forms for custom logic
  • TypeScript: Full type safety

How It Works

Built-in Auth Flow

1. User clicks "Sign In" → Visits /sign-in route

2. getInsforgeRoutes() redirects → https://your-app.region.insforge.app/auth/sign-in?redirect=yourapp.com/you-defined-destination-after-sign-in

3. User signs in on deployed page → Backend processes authentication

4. Backend redirects → yourapp.com/you-defined-destination-after-sign-in?access_token=xxx&user_id=xxx

5. InsForge SDK will:
   - Extracts token from URL
   - Saves to localStorage
   - Verifies with getCurrentUser()
   - Updates Provider state

6. User sees the destination page (e.g /dashboard)

Custom UI Flow

1. User visits /sign-in route → Renders <SignIn> component

2. User enters credentials → Component calls SDK methods

3. SDK communicates with backend → Returns auth token and user data

4. Component adds token to URL and redirects → SDK auto-detects token from URL

5. Provider automatically updates auth state → Components re-render

6. User sees authenticated UI at destination
Architecture:
  • InsforgeProvider: Manages authentication state globally using React Context
  • getInsforgeRoutes(): Creates redirect routes for built-in auth
  • SDK Integration: All auth operations go through @insforge/sdk, which auto-detects tokens from URL
  • React Context: Provides auth state to all child components
  • Hooks: Easy access to auth methods and user data

Complete Components (with Business Logic)

These components include full authentication logic and work out of the box.

<SignIn />

Complete sign-in component with email/password and OAuth:
import { SignIn } from '@insforge/react-router';

function SignInPage() {
  return (
    <SignIn
      title="Welcome Back"
      subtitle="Sign in to continue"
      onError={(error) => {
        console.error('Error:', error);
      }}
    />
  );
}
Key Features:
  • Email/password authentication
  • OAuth provider buttons (auto-detected from backend)
  • Password visibility toggle
  • Error handling
  • Loading states
  • Customizable text
Props:
  • onError - Callback on error
  • title / subtitle - Custom heading text

<SignUp />

Complete sign-up component with password strength validation:
import { SignUp } from '@insforge/react-router';

function SignUpPage() {
  return (
    <SignUp
      title="Create Account"
      subtitle="Get started with your free account"
      onError={(error) => {
        console.error('Error:', error);
      }}
    />
  );
}
Key Features:
  • Email/password registration
  • Real-time password strength indicator
  • OAuth provider buttons
  • Form validation
  • Customizable text
Props: Same as <SignIn>.

<UserButton />

User profile dropdown with sign-out:
import { UserButton } from '@insforge/react-router';

function Header() {
  return (
    <header>
      <nav>{/* Your navigation */}</nav>
      <UserButton afterSignOutUrl="/" mode="detailed" />
    </header>
  );
}
Modes:
  • detailed (default): Shows avatar + name + email
  • simple: Shows avatar only
Props:
  • mode - Display mode: "detailed" or "simple"
  • afterSignOutUrl - Redirect URL after sign out

<ForgotPassword />

Complete password reset flow with automatic method detection:
import { ForgotPassword } from '@insforge/react-router';

function ForgotPasswordPage() {
  return (
    <ForgotPassword
      onError={(error) => {
        console.error('Error:', error);
      }}
    />
  );
}
Key Features:
  • Auto-detects reset method (code or link) from backend config
  • Link method: Sends email with reset link
  • Code method: Three-step flow (email → verify code → reset password)
  • 60-second countdown timer for resend
  • Built-in form validation
  • Customizable text
Props:
  • onError - Callback on error

<Protect />

Protected content with conditional rendering:
import { Protect } from '@insforge/react-router';

function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>
      {/* Simple protection */}
      <Protect redirectTo="/sign-in">
        <UserContent />
      </Protect>
      {/* Custom logic */}
      <Protect condition={(user) => user.subscription === 'premium'} fallback={<UpgradePrompt />}>
        <PremiumFeature />
      </Protect>
    </div>
  );
}
Props:
  • redirectTo - URL to redirect if not authorized
  • condition - Custom condition function (user) => boolean
  • fallback - React node to show if not authorized

<SignedIn> / <SignedOut>

Conditional rendering based on auth state:
import { SignedIn, SignedOut } from '@insforge/react-router';

function NavBar() {
  return (
    <nav>
      <SignedOut>
        <a href="/sign-in">Sign In</a>
        <a href="/sign-up">Sign Up</a>
      </SignedOut>

      <SignedIn>
        <a href="/dashboard">Dashboard</a>
        <UserButton />
      </SignedIn>
    </nav>
  );
}

Hooks

useAuth()

Access authentication methods and state:
import { useAuth } from '@insforge/react-router';

function LoginButton() {
  const { signIn, signUp, signOut, isSignedIn, isLoaded } = useAuth();

  const handleSignIn = async () => {
    try {
      await signIn('[email protected]', 'password');
    } catch (error) {
      console.error('Sign in failed:', error);
    }
  };

  if (!isLoaded) return <div>Loading...</div>;

  return (
    <button onClick={isSignedIn ? signOut : handleSignIn}>
      {isSignedIn ? 'Sign Out' : 'Sign In'}
    </button>
  );
}
Returns:
  • signIn(email, password) - Sign in with email/password
  • signUp(email, password) - Sign up new user
  • signOut() - Sign out current user
  • isSignedIn - Boolean auth state
  • isLoaded - Boolean loading state

useUser()

Access current user data:
import { useUser } from '@insforge/react-router';

function UserProfile() {
  const { user, isLoaded, updateUser } = useUser();

  if (!isLoaded) return <div>Loading...</div>;
  if (!user) return <div>Not signed in</div>;

  const handleUpdate = async () => {
    await updateUser({ name: 'New Name' });
  };

  return (
    <div>
      <p>Email: {user.email}</p>
      <p>Name: {user.profile.name}</p>
      <img src={user.profile.avatar_url} alt="Avatar" />
      <button onClick={handleUpdate}>Update Name</button>
    </div>
  );
}
Returns:
  • user - User object with id, email, profile
  • user.profile - User profile object with name, avatar_url, and other custom fields
  • isLoaded - Boolean loading state
  • updateUser(data) - Update user profile

usePublicAuthConfig()

Get your authentication config in InsForge:
import { usePublicAuthConfig } from '@insforge/react-router';

function SignInPage() {
  const { authConfig, isLoaded } = usePublicAuthConfig();

  if (!isLoaded) return <div>Loading...</div>;

  return (
    <div>
      <p>Available OAuth: {authConfig.oAuthProviders.join(', ')}</p>
      <p>Password min length: {authConfig?.passwordMinLength}</p>
    </div>
  );
}
Returns:
  • authConfig - Authentication Configuration you set in InsForge dashboard.
  • isLoaded - Boolean loading state
Performance: Only use this hook in SignIn/SignUp components to avoid unnecessary API calls.

Advanced Features

Auth Change Callback

Track authentication state changes:
<InsforgeProvider
  baseUrl={baseUrl}
  onAuthChange={(user) => {
    if (user) {
      console.log('User signed in:', user.email);
      analytics.identify(user.id);
    } else {
      console.log('User signed out');
      analytics.reset();
    }
  }}
>
  {children}
</InsforgeProvider>