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:
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:
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>.
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>