Skip to main content

Custom Authentication system

Use this approach when you need custom authentication pages in your application instead of redirecting to hosted pages.

Step-by-Step: Custom Auth Pages Setup

Step 1: Setup Provider (Same as Quick Start)

The provider setup is identical:
src/main.tsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { InsforgeProvider } from '@insforge/react-router';
import App from './App';

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <InsforgeProvider
      baseUrl={
        import.meta.env.VITE_INSFORGE_BASE_URL || 'https://your-app.region.insforge.app' // Replace with your InsForge backend URL
      }
      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.name}</p>
      <img src={user.avatarUrl} alt="Avatar" />
      <button onClick={handleUpdate}>Update Name</button>
    </div>
  );
}
Returns:
  • user - User object with id, email, name, avatarUrl
  • 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>