Installation
Prerequisites and minimum installation steps for the Impersona SDK.
This guide covers prerequisites, installation, and configuration in detail. If you want the shortest path to a working setup, start with the Quickstart.
Prerequisites
- A running app with authentication (the SDK impersonates authenticated users — there's nothing to impersonate without auth)
- A local environment where you can run and test requests
- Access to your app's auth or session middleware (you may need to read the impersonation token header)
- An Impersona project with a generated publishable key and your frontend origin in Allowed Origins
Install the SDK
npm install @impersona/sdkEnvironment variables
Add your project credentials to your .env. Select your framework to see the correct variable prefix:
Required:
VITE_IMPERSONA_PROJECT_ID=proj_abc123
VITE_IMPERSONA_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxxxxxOptional (only if self-hosting):
VITE_IMPERSONA_API_BASE_URL=http://localhost:3002/api/v1Required:
NEXT_PUBLIC_IMPERSONA_PROJECT_ID=proj_abc123
NEXT_PUBLIC_IMPERSONA_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxxxxxOptional (only if self-hosting):
NEXT_PUBLIC_IMPERSONA_API_BASE_URL=http://localhost:3002/api/v1Required:
REACT_APP_IMPERSONA_PROJECT_ID=proj_abc123
REACT_APP_IMPERSONA_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxxxxxOptional (only if self-hosting):
REACT_APP_IMPERSONA_API_BASE_URL=http://localhost:3002/api/v1If omitted, the SDK defaults to the hosted Impersona backend.
Configure the provider
Wrap your app with ImpersonaProvider and render ImpersonaWidget:
import { ImpersonaProvider } from '@impersona/sdk'
import { ImpersonaWidget } from '@impersona/sdk/widget'
export function App() {
return (
<ImpersonaProvider
projectId={import.meta.env.VITE_IMPERSONA_PROJECT_ID}
publishableKey={import.meta.env.VITE_IMPERSONA_PUBLISHABLE_KEY}
apiBaseUrl={import.meta.env.VITE_IMPERSONA_API_BASE_URL || undefined}
enabled={import.meta.env.DEV}
refreshStrategy={{ type: 'reload' }}
>
{/* your app tree */}
<ImpersonaWidget />
</ImpersonaProvider>
)
}import { ImpersonaProvider } from '@impersona/sdk'
import { ImpersonaWidget } from '@impersona/sdk/widget'
export function App() {
return (
<ImpersonaProvider
projectId={process.env.NEXT_PUBLIC_IMPERSONA_PROJECT_ID!}
publishableKey={process.env.NEXT_PUBLIC_IMPERSONA_PUBLISHABLE_KEY!}
apiBaseUrl={process.env.NEXT_PUBLIC_IMPERSONA_API_BASE_URL || undefined}
enabled={process.env.NODE_ENV === 'development'}
refreshStrategy={{ type: 'reload' }}
>
{/* your app tree */}
<ImpersonaWidget />
</ImpersonaProvider>
)
}import { ImpersonaProvider } from '@impersona/sdk'
import { ImpersonaWidget } from '@impersona/sdk/widget'
export function App() {
return (
<ImpersonaProvider
projectId={process.env.REACT_APP_IMPERSONA_PROJECT_ID!}
publishableKey={process.env.REACT_APP_IMPERSONA_PUBLISHABLE_KEY!}
apiBaseUrl={process.env.REACT_APP_IMPERSONA_API_BASE_URL || undefined}
enabled={process.env.NODE_ENV === 'development'}
refreshStrategy={{ type: 'reload' }}
>
{/* your app tree */}
<ImpersonaWidget />
</ImpersonaProvider>
)
}Provider props
| Prop | Required | Purpose |
|---|---|---|
projectId | Yes | Must match the project ID in the dashboard |
publishableKey | Yes | Must match the key generated in the dashboard |
apiBaseUrl | No | Override the hosted backend URL (self-hosting only) |
enabled | No | Gates the SDK on/off — use to disable in production |
refreshStrategy | No | How the app refreshes after applying a preset (reload or soft) |
tokenAdapter | No | Custom fetch interceptor (see below) |
Default adapter behavior
When no tokenAdapter is passed, the provider creates a FetchInterceptorAdapter with:
allowedOrigins: same-origin only — the adapter only patches requests to your app's own APIexcludePatterns:[apiBaseUrl]— SDK-internal calls to the Impersona backend are automatically excluded so they use the publishable key, not the impersonation token
This default is correct for most setups where your frontend and API share the same origin.
Custom adapter (cross-origin APIs)
If your frontend and API are on different origins, you need a custom adapter:
import { useMemo } from 'react'
import { FetchInterceptorAdapter, ImpersonaProvider } from '@impersona/sdk'
export function App() {
const apiBaseUrl =
import.meta.env.VITE_IMPERSONA_API_BASE_URL || 'https://app.impersona.co.uk/api/v1'
const adapter = useMemo(
() =>
new FetchInterceptorAdapter({
allowedOrigins: ['https://api.myapp.com'],
excludePatterns: [apiBaseUrl],
}),
[apiBaseUrl],
)
return (
<ImpersonaProvider
projectId={import.meta.env.VITE_IMPERSONA_PROJECT_ID}
publishableKey={import.meta.env.VITE_IMPERSONA_PUBLISHABLE_KEY}
apiBaseUrl={import.meta.env.VITE_IMPERSONA_API_BASE_URL || undefined}
tokenAdapter={adapter}
enabled={import.meta.env.DEV}
refreshStrategy={{ type: 'reload' }}
>
{/* your app tree */}
</ImpersonaProvider>
)
}import { useMemo } from 'react'
import { FetchInterceptorAdapter, ImpersonaProvider } from '@impersona/sdk'
export function App() {
const apiBaseUrl =
process.env.NEXT_PUBLIC_IMPERSONA_API_BASE_URL || 'https://app.impersona.co.uk/api/v1'
const adapter = useMemo(
() =>
new FetchInterceptorAdapter({
allowedOrigins: ['https://api.myapp.com'],
excludePatterns: [apiBaseUrl],
}),
[apiBaseUrl],
)
return (
<ImpersonaProvider
projectId={process.env.NEXT_PUBLIC_IMPERSONA_PROJECT_ID!}
publishableKey={process.env.NEXT_PUBLIC_IMPERSONA_PUBLISHABLE_KEY!}
apiBaseUrl={process.env.NEXT_PUBLIC_IMPERSONA_API_BASE_URL || undefined}
tokenAdapter={adapter}
enabled={process.env.NODE_ENV === 'development'}
refreshStrategy={{ type: 'reload' }}
>
{/* your app tree */}
</ImpersonaProvider>
)
}import { useMemo } from 'react'
import { FetchInterceptorAdapter, ImpersonaProvider } from '@impersona/sdk'
export function App() {
const apiBaseUrl =
process.env.REACT_APP_IMPERSONA_API_BASE_URL || 'https://app.impersona.co.uk/api/v1'
const adapter = useMemo(
() =>
new FetchInterceptorAdapter({
allowedOrigins: ['https://api.myapp.com'],
excludePatterns: [apiBaseUrl],
}),
[apiBaseUrl],
)
return (
<ImpersonaProvider
projectId={process.env.REACT_APP_IMPERSONA_PROJECT_ID!}
publishableKey={process.env.REACT_APP_IMPERSONA_PUBLISHABLE_KEY!}
apiBaseUrl={process.env.REACT_APP_IMPERSONA_API_BASE_URL || undefined}
tokenAdapter={adapter}
enabled={process.env.NODE_ENV === 'development'}
refreshStrategy={{ type: 'reload' }}
>
{/* your app tree */}
</ImpersonaProvider>
)
}Important: When creating a custom adapter, you must include apiBaseUrl in excludePatterns. Otherwise the adapter injects the impersonation token into SDK-internal calls, causing auth failures on preset fetches. Also avoid path fragments like /api/v1 in excludePatterns — they match your host app's own routes too, preventing impersonation tokens from reaching your API.
Host integration (required)
Impersona can send a token, but your host must know how to read it. Choose one of these patterns:
-
Authorization swap — Impersona replaces the
Authorizationheader. Your API already readsAuthorization: Bearer <token>, so no backend changes are needed. -
Custom header — Impersona sends
X-Impersona-Token(or another header you choose). Your host reads that header and resolves the impersonated identity. Requires a small middleware change. -
Cookie session — Your host reads an Impersona token header and creates a session. Useful for apps that rely on cookie-based auth.
See Auth Strategies for detailed guidance on each pattern.
Environment safety
The enabled prop is the primary gate. Set it to a development-only condition:
enabled={import.meta.env.DEV}enabled={process.env.NODE_ENV === 'development'}When enabled is false, the SDK renders nothing and does not intercept any requests.
For additional strategies (conditional imports, build-time exclusion, feature flags), see the environment safety section in the configuration alignment reference.