Skip to main content

Widget Identity

Widget identity connects a visitor to a stable customer record and conversation history.
Unsigned identify fields are display and routing metadata, not authentication. Any browser user can alter them. Use HMAC or JWT identity verification before showing account-specific history or trusting account/customer ids.

Modes

How Verification Is Enforced

Woes uses the same model as Intercom: verification protects identified users without locking out anonymous ones:
  • Anonymous visitors with no identify call, or identify with no email, can always chat as leads. Turning on verification never blocks them.
  • Identified visitors must carry a valid HMAC hash or JWT when they pass an email. An identity claim without a valid proof is rejected, so a browser user can never impersonate another account.
  • Strict mode blocks anonymous visitors entirely. Turn on Require verified identity only when everyone must be verified before chatting.
Enable a mode from Settings → Security. Choose the agent widget key first, then set that agent’s verification mode, generate its identity secret, and optionally toggle strict mode. Use separate agent widget keys and secrets when Woes is installed on different sites. For example, your docs site can use a docs-focused agent and JWT, while a marketing site can use a lead-support agent with anonymous chat.

Install Contract

Verified identity has a hard public/private split: Your app should expose an authenticated, no-store endpoint, such as /api/woes-identity, that returns the signed proof for the current logged-in user. The browser should fetch that endpoint and call window.Woes("identify", ...):
  • After login or session load.
  • When https://woes.dev/widget.js finishes loading.
  • On window focus.
  • When the page becomes visible again.
Calling identify repeatedly for the same current user is safe. Do not suppress retries for the same HMAC or JWT before Woes has accepted it; retries prevent boot-order races from leaving a logged-in customer anonymous.
The script tag and the identity proof must use the same selected agent widget key. A valid HMAC or JWT for one agent does not verify a visitor on another agent’s widget key.
The identity secret is private signing material. Keep it on your server only. Do not paste it into client JavaScript, mobile apps, documentation, or AI coding prompts.

Verify an Install

Use Settings → Security to confirm both halves of the integration:
  1. Select the agent widget key installed on the site.
  2. Open the site page where the widget script is installed.
  3. In Woes, click Refresh in Install check. The site origin should appear with a recent last seen time.
  4. Generate a real identity proof from your application backend.
  5. Paste the customer email and email_hash for HMAC mode, or paste the JWT for JWT mode, into Test an identity proof.
  6. Click Verify proof before testing a live chat message.
If the proof fails, check that the backend uses the identity secret from the same selected agent, that the browser snippet uses that agent’s public widget key, and that the email is normalized with trim().toLowerCase() before signing.

HMAC Email

In HMAC mode, your backend signs the normalized customer email using the selected agent widget’s identity secret. The browser sends the email and hash to Woes. Only the normalized email is verified. name, company, and id remain display metadata. Use JWT when account or contact ids must be verified.
Send the returned identity payload to the widget in the browser.
Call identify after your backend returns the proof and before the visitor sends their first message. The widget asks Woes to verify the proof before it treats the visitor as verified.

JWT

In JWT mode, your backend signs a token that includes the customer’s email and optional identity fields. Woes verifies the token before trusting the identity.
Then identify the visitor with the signed token.
JWT identity tokens must use HS256, include an email claim, and set aud to the widget public key used by the install snippet. Keep token lifetimes short; Woes accepts verified widget identity JWTs up to 15 minutes from issue to expiry.

Browser Integration Checklist

  • Load https://woes.dev/widget.js with the selected public widget key in data-public-key.
  • Create or rely on the Woes command queue before calling window.Woes(...).
  • Fetch your authenticated identity endpoint with same-origin credentials and no-store caching.
  • Treat 401 from the identity endpoint as anonymous mode unless strict verified identity is required.
  • Call window.Woes("identify", identity) every time a valid signed identity is returned.
  • Verify a logged-in test visitor sends a message and appears in Woes with their email/name and identity_source of widget-token.
The aud claim must exactly match the data-public-key in the installed widget script.

Copy Prompt for AI Install

Settings → Security includes Copy prompt for AI install after you select an agent widget key. Paste that prompt into your coding assistant to install the widget and create the server endpoint that mints the HMAC hash or JWT. The copied prompt intentionally includes:
  • The public widget key for the selected agent.
  • The selected verification mode.
  • Server-only environment variable guidance.
  • The authenticated no-store identity endpoint contract.
  • The required browser window.Woes("identify", ...) call and retry behavior.
The copied prompt intentionally excludes:
  • The private identity secret.
  • Workspace API keys.
  • Supabase or Stripe keys.
  • Operator-only account data.

Security Rules

  • Generate signatures server-side.
  • Never expose identity secrets to the browser.
  • Use stable customer identifiers.
  • Do not include raw secrets in identity metadata.
  • Confirm the widget install uses the correct workspace or agent key.
  • Treat unsigned browser identity fields as untrusted metadata.
A widget public key is public. It identifies the workspace or agent install, but it is not a private authentication secret.
Last modified on July 2, 2026