Next liveBuild Your Chief of Staff · OnlineSave your seat →
Monetization & Access

Bring Your Own Auth (Pre-Authenticated Sessions)

Sign users into your Chipp app from your own backend -- no Chipp login screen -- with server-side identity that works across devices and inside iframe embeds.

|View as Markdown
Hunter Hodnett
Co-founder and co-CEO
||1 min read
#authentication#sso#embed#api#security#sessions

If your application already authenticates its users (WorkOS, Auth0, Clerk, Okta, a custom SSO, or your own signed links), you do not need to make them sign in again inside Chipp. Your backend can mint a Chipp session for a user it has already verified, and the chat opens pre-authenticated: no login screen, no OTP, no Chipp password.

This is the recommended pattern for white-label deployments, portals behind your own login, and governed workflows (for example, sending a patient or client a protected link that opens a pre-authenticated chat).

ℹ️

Because the consumer identity created this way lives on Chipp’s servers (keyed by email), it is portable across devices: any device where your backend mints a token for the same email is the same consumer, with the same conversation history.

How It Works

plaintext
User opens your app or your protected link
    1. Your backend verifies the user (your auth, your signature checks)
    2. Your backend calls POST /api/v1/apps/{appId}/consumers/auth
       -> Chipp finds or creates the consumer and returns a bearer token
    3. Your page passes the token to the embedded chat
       -> the user is signed in, no Chipp login screen

Chipp never sees or validates your credentials or signed links. Your backend is the authority: it decides who gets a token, and Chipp trusts the Builder API call because it carries your secret API key.

Step 1: Mint a Token on Your Server

Call the Builder API endpoint POST /api/v1/apps/{appId}/consumers/auth from your backend. It requires a Builder API key with consumers:write scope (ask the Alchemist: “Create a Builder API key for this app”).

bash
curl -X POST https://build.chipp.ai/api/v1/apps/YOUR_APP_ID/consumers/auth \
  -H "Authorization: Bearer chipp_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "jane@example.com",
    "name": "Jane Doe",
    "metadata": { "accountTier": "enterprise", "projectId": "PRJ-4821" }
  }'

Response:

json
{
  "data": {
    "token": "YjNmZDQ1YzQt...",
    "consumer": { "id": "...", "email": "jane@example.com", "name": "Jane Doe" },
    "expires_at": "2026-08-16T10:00:00Z"
  }
}

What happens server-side: Chipp finds or creates the consumer by email (lower-cased and trimmed), applies any name and metadata you send, creates a session, and returns a bearer token for it.

Token lifetime: sessions last 30 days by default. When HIPAA mode is enabled on the app, sessions last 4 hours instead. Either way, the simplest robust pattern is to mint a fresh token on every page load: the call is idempotent, cheap, and metadata is upserted per key on each call.

⚠️

Never call this endpoint from the browser. The Builder API key must stay on your server — anyone holding it can mint a session for any email on your app.

Users Without a Real Email

The email is the identity key, not a delivery address. If your users should not be identified by their real email (or do not have one), use a stable synthetic email per user, for example user-8f3a@yourdomain.com. As long as your backend always maps the same user to the same synthetic address, their identity and history stay consistent.

Step 2: Pass the Token to the Chat

For the embed widget, call ChippWidget.setUser once the widget is loaded:

javascript
ChippWidget.setUser({
  email: "jane@example.com",
  name: "Jane Doe",
  token: "YjNmZDQ1YzQt..." // from your backend
});

The token authenticates the user inside the chat iframe without cookies, so it works reliably in cross-origin iframe embeds even under Safari ITP and Chrome third-party cookie restrictions.

Several Chipp Agents Behind One Login

If your app shows more than one Chipp agent (for example three assistants for different teams), your users still sign in to your app once. They are never asked to log in to Chipp, and never once per agent. Each agent is its own Chipp app, so your backend mints one token per agent:

plaintext
User signs in to your app once
    1. Your backend verifies the user
    2. For each agent the user can open, your backend calls
       POST /api/v1/apps/{thatAgentsAppId}/consumers/auth
       with that agent's own Builder API key
       -> one token per agent
    3. Your page passes each token to the matching embed
       ChippWidget.setUser({ email, name, token })
       -> no Chipp login prompt in any agent
javascript
// Server: one mint per target app, each with that app's own key
const AGENTS = [
  { appId: process.env.CHIPP_APP_ID_SALES, key: process.env.CHIPP_KEY_SALES },
  { appId: process.env.CHIPP_APP_ID_SUPPORT, key: process.env.CHIPP_KEY_SUPPORT },
  { appId: process.env.CHIPP_APP_ID_HR, key: process.env.CHIPP_KEY_HR },
];

async function mintTokens(user) {
  return Promise.all(
    AGENTS.map(async ({ appId, key }) => {
      const res = await fetch(`https://build.chipp.ai/api/v1/apps/${appId}/consumers/auth`, {
        method: "POST",
        headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" },
        body: JSON.stringify({ email: user.email, name: user.name }),
      });
      if (!res.ok) throw new Error(`Chipp mint failed for ${appId}: ${res.status}`);
      const { data } = await res.json();
      return { appId, token: data.token };
    }),
  );
}

Rules for the multi-agent case:

  • One key per app. A Builder API key belongs to one app. Using it on another app’s /consumers/auth path returns 403. Keep all the keys on your server.
  • Identity is app-local. The same verified email gives the user a stable identity inside each agent, so each agent keeps that user’s history across visits. Chipp does not merge history, memory, files, or billing across agents. There is no shared cross-app consumer record.
  • Keys never reach the browser. Only the short-lived token goes to the page.
  • Use Required auth mode on every agent, so a broken token path ends at a login gate and never as silent anonymous chat.
  • Mint fresh tokens on every page load. Sessions last 30 days, or 4 hours when HIPAA mode is on for that agent.
  • One widget per page. The embed script creates a single window.ChippWidget on a page. Load one agent’s embed per page or view and pass it that agent’s token. If you frame an agent yourself, send its iframe a chipp:identify message with a payload holding email, name, and token.

Is the Embedded Chipp Agent Feature Pack Required?

No. The Embedded Chipp Agent Feature Pack is optional chat UI and runtime scaffolding for a native chat panel inside an app you build with the Chipp Builder, with no iframe. It binds one agent to one project. It has nothing to do with whether your login is trusted: server-side identify and pre-authenticated sessions work with the plain embed widget. They need no pack, no purchase, and no agent binding.

Auth Modes

Server-side tokens work with every auth mode. The mode only controls what a user sees when no token is present:

Auth modeWithout a tokenWith a server-minted token
OpenAnonymous chatSigned in as the identified user
EncouragedInline sign-in card, can dismissSigned in, no card
Required / RestrictedFull-screen sign-in gateSigned in, no gate

For governed deployments where nobody should ever chat anonymously, use Required: if your token wiring fails, users hit a login gate instead of silently chatting as anonymous consumers.

Cross-Device Behavior and Session Continuity

Understanding what is and is not continuous across devices:

  • Identity and history are server-side. The same email on any device is the same consumer. All of their past conversations are available in the in-chat history panel on every device.
  • A new visit starts a fresh conversation thread by default. Within the same browser tab, an in-progress session is restored automatically, but opening the app on a new device (or after the idle timeout) starts a new thread. The user can reopen any prior conversation from history.
  • There is no session-addressing parameter. You cannot pass a session ID in the URL or embed configuration to force the chat to open a specific conversation, and the embed does not expose session IDs to the parent page via postMessage.

If your application needs to continue a structured workflow mid-stream across devices (for example, a multi-step interview), the supported pattern is to keep workflow state in your backend and have the agent reconstruct it: pass your own reference ID on the arrival URL, have a custom action fetch current progress on the first turn (or seed it via the metadata field when minting the token), and treat each Chipp session as an execution context rather than the source of truth.

Tracking Sessions From Your Backend

You do not need anything in-conversation to learn which Chipp session belongs to which of your users:

  • Session webhooks send your endpoint a signed session.created event the moment any session starts, containing the sessionId, consumerId, externalId, and all captured URL query params. This is the deterministic way to build a your-user-id -> chipp-session-id mapping, with no model involvement.
  • ?chipp_external_id= on the arrival URL is promoted to a first-class externalId field on the session (colon-free values only) and appears in the Conversations tab, session webhooks, the Sessions API, and all exports. Use it to stamp sessions with your own user or case reference.
  • The Sessions API lets your backend fetch any session’s transcript by sessionId at any time, and the Org Export API covers org-wide retrieval.

Per-User Context for the Agent

The optional metadata object on the mint call is upserted per key onto the consumer and rendered under an ## About this user block in the agent’s system prompt on every session. Use it for things your backend already knows (role, account tier, project, internal IDs) so the agent has them from the first message, with no custom action round-trip. Full schema and limits: Authenticate a Consumer (Server-Side).

Chipp apps also support email magic links: POST /consumer/YOUR_APP_SLUG/auth/magic-link with an email causes Chipp to email that user a single-use sign-in link (valid 7 days). Opening it signs them in with the same server-side, cross-device identity, no password. This is useful when you want Chipp to handle link delivery. The server-side identify flow above is strictly more flexible for white-label integrations because your backend controls exactly when and for whom sessions are created, and nothing depends on email delivery.