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