<IntelliAuthProvider /> is the React context that everything else depends on. You mount it once, near the top of the tree, and every component below can call useIntelliAuth().
Minimum usage
Section titled “Minimum usage”import { IntelliAuthProvider } from '@intelliauth/react-sdk'import { createRoot } from 'react-dom/client'import App from './App'
createRoot(document.getElementById('root')!).render( <IntelliAuthProvider tenantUrl="https://banking-cymmetri.intelliauth.local" clientId="app_01HZX..." redirectUri={`${window.location.origin}/callback`} > <App /> </IntelliAuthProvider>,)Three props are required. The rest have sensible defaults.
| Prop | Type | Required | Description |
|---|---|---|---|
tenantUrl | string | yes | The base URL of your IntelliAuth tenant. E.g., https://banking-cymmetri.intelliauth.local. No trailing slash. |
clientId | string | yes | The application's client id. Visible on the application's detail page in the tenant admin console. |
redirectUri | string | yes | The URL the browser is sent back to after sign-in. Must be one of the redirect URIs registered on the application. |
scope | string | no | Space-separated scopes to request. Defaults to openid profile email offline_access. |
audience | string | string[] | no | The audience(s) you want in the access token. Defaults to tenantUrl + '/api'. |
logoutReturnTo | string | no | Where to send the browser after sign-out. Defaults to window.location.origin. |
silentRefresh | boolean | no | Whether to auto-refresh the access token before it expires. Defaults to true. |
silentRefreshLeeway | number | no | Seconds before exp to trigger refresh. Defaults to 60. |
useRefreshTokens | boolean | no | Whether to store and use refresh tokens. Defaults to true. If false, silent refresh uses iframe-hosted silent auth instead. |
onLogin | (user) => void | no | Callback when a user signs in successfully. |
onLogout | () => void | no | Callback when a user signs out. |
onTokenRefresh | (tokens) => void | no | Callback when tokens are silently refreshed. |
onError | (error) => void | no | Global error handler. Receives IntelliAuthError instances. |
cacheLocation | 'memory' | 'localstorage' | no | Where to persist tokens. Defaults to memory for the access token, an HttpOnly cookie for the refresh token. Setting localstorage makes tokens survive a tab close at the cost of XSS exposure. |
The provider must wrap every component that calls useIntelliAuth(). Calling the hook outside the provider throws.
Reading from environment variables
Section titled “Reading from environment variables”The common pattern is to source the tenant URL and client id from build-time env vars so dev / staging / prod can use different tenants without code changes:
<IntelliAuthProvider tenantUrl={import.meta.env.VITE_INTELLIAUTH_TENANT_URL!} clientId={import.meta.env.VITE_INTELLIAUTH_CLIENT_ID!} redirectUri={`${window.location.origin}/callback`}> <App /></IntelliAuthProvider>Vite, Next.js, Remix, and similar frameworks all support build-time env vars; check your framework's docs for the right prefix (Vite uses VITE_, Next.js uses NEXT_PUBLIC_).
Single instance
Section titled “Single instance”Mount the provider exactly once. Two providers in the same tree create two independent sessions; they will fight each other on silent refresh and tabs will desync. The provider is designed to live at the root of the app and stay mounted for the app's lifetime.
If you have a portal-mounted modal that needs IntelliAuth, ensure it lives inside the provider's tree (React's createPortal keeps context flowing through the portal — usually fine — but be aware of structure).
Server-side rendering (SSR)
Section titled “Server-side rendering (SSR)”For Next.js or Remix, render the provider only on the client. The provider needs window, localStorage, and BroadcastChannel, none of which exist on the server. Two patterns:
- Wrap the provider in a
'use client'component (Next.js App Router). - Render the provider conditionally on
typeof window !== 'undefined'.
The user record is still server-renderable if you fetch it server-side via the Node SDK and pass it as initial state; the provider hydrates from there.
Lifecycle
Section titled “Lifecycle”- Mount. The provider creates an internal
AuthClient. If a session cookie is present on the tenant, the client silently bootstraps — it fetches the access token via the silent-auth endpoint, then the user profile. - Render. The
loadingflag istrueuntil bootstrap completes. Render a splash / skeleton during this window. - Active. From here,
useris either null (signed out) or populated. The silent-refresh timer runs in the background. - Unmount. Rare in production. If it happens, the silent-refresh timer is cleared.
Common pitfalls
Section titled “Common pitfalls”- Forgetting
redirectUri. The SDK will error at sign-in time; the error mentions the missing prop. - Mismatched
redirectUriand the application's registered URI. Down to the trailing slash; whitespace; protocol. Re-check on both sides. - Wrapping only a portion of the tree. If a route's component lives outside the provider,
useIntelliAuth()throws when that route mounts. - Memory vs localstorage cache. Memory is the secure default; switching to localstorage is a trade. Do not switch without understanding the XSS implications.