Skip to main content
When a user signs in to your website, your server can identify them to the Centillion widget, so you verify logged-in users in the AI chat widget instead of trusting what they type. The widget links their conversation to the contact with the same External ID, signed JWT fields update that contact, and public attributes give the agent context for its replies.

What it does

  • Links a signed-in visitor’s chat to the contact with the same External ID, creating the contact when none exists.
  • Accepts a JWT signed with HS256, whose exp claim, when present, is at most 24 hours ahead (include one, so the token stops working), or a legacy HMAC-SHA256 user hash.
  • Updates the contact’s email, name, phone, custom attributes and Stripe customer IDs from signed JWT fields.
  • Passes public attributes, up to 1,000 characters of JSON, to the agent as context.
  • Gives actions such as Stripe billing the verified customer, so they act only on that person’s records. A Twilio action scoped to the customer uses the verified number too; one set to any number does not.

What you need

  • Standard and up. If the workspace loses that plan access, visitors can still chat anonymously, but the agent stops loading their verified contact details. See plans.
  • A workspace admin to turn verification on, copy the secrets and rotate them.
  • A server that already authenticates your users and can sign a token.
  • The website widget installed; see the website widget.
If you are new to the product, start with what Centillion is.

Set it up

1

Open Identity

Open Channels → Install → Website widget → Set up identity verification. You can also open Settings → Identity. Choose Turn on identity verification the first time.
2

Copy the secrets

The Identity verification card shows two secrets, one for each method: a Token secret for JWTs and a User hash secret for user hashes. Store them on your server as CENTILLION_TOKEN_SECRET and CENTILLION_USER_HASH_SECRET.
3

Pick a signing method

Under Set it up, choose Token (JWT) or User hash (legacy). The page shows the server code and the website code for that method.
4

Sign and identify

After login, sign a JWT on your server, or generate the user hash if you chose the legacy method, then pass it to the widget with identify or centillionUserConfig, as below.
5

Choose what the agent may read

Under What the agent may read, select the contact attributes the agent may use in its answers.
Keep both secrets on your server. Never put them in browser JavaScript, an embed snippet, or a public environment variable.
Verification used to have one shared secret, often kept in CENTILLION_IDENTITY_SECRET. That secret no longer verifies either kind of signature. Copy the Token secret for JWTs or the User hash secret for user hashes from Settings → Identity, and update your server.

Use it every day

After authenticating the user with your existing login system, sign a token on your server. Derive the user ID from that authenticated session.
Only user_id or sub is required. Use a stable string identifier. Numeric user_id values are also accepted and converted to strings. If both are present, sub takes precedence. phone is an alias for phonenumber and takes precedence, including when set to null. Expiration is optional, but use a short-lived token and refresh it while the website session remains valid. When supplied, exp must be no more than 24 hours away. Expired tokens, future nbf claims, wrong signatures and algorithms other than HS256 do not authenticate the visitor. Verification allows one minute of clock skew. JWTs are signed, not encrypted, so keep passwords and other secrets out of them.

Identify after login

Return the token from your authenticated backend endpoint, then pass it to the widget. The endpoint below is part of your website and uses your website session.
Identification creates or updates the contact even if the widget has not been opened. The widget verifies the signed identity again for each chat request. window.centillion("identify", ...) is also supported.

Identify before the script loads

Set the configuration before your normal embed snippet:
window.centillionSettings remains supported. If both configurations are set, centillionUserConfig takes precedence. Provide a fresh token on each page load. If login can finish before the script loads, define this command queue first:

Sign out

Call this when your website signs the user out:
This clears the widget identity, public metadata and conversation. Signing in as another user also starts a new conversation. Refreshing a token for the same user preserves the current conversation. The existing logout and shutdown commands remain supported.

Contact updates and privacy

JWT fields are private contact data. They are available to configured actions, including billing actions, and are not automatically added to the AI context. In Settings → Identity → What the agent may read, you can explicitly expose selected contact attributes. Billing identifiers remain private. Omitted fields keep their current values. Pass null to clear a field. For custom attributes, {"plan": null} deletes only plan; custom_attributes: null clears defined custom attributes while preserving billing IDs. stripe_accounts: null or [] clears the billing mapping. Email and phone values already held by another contact are not reassigned. Attributes are defined under Contacts, Manage attributes.
Attributes outside the token are visible to the AI agent. Keep them free of confidential information. They provide context and never prove permissions, select a billing customer, or update the contact.
Public attributes can be supplied directly beside token, or inside user_metadata. Their combined JSON must fit within 1,000 characters. Oversized or malformed metadata is ignored without discarding a valid identity.

Method 2: user hash, legacy

For existing integrations, generate an HMAC-SHA256 of the exact user ID on your server, keyed with the User hash secret. Prefer JWTs for new integrations because they support expiration and contact updates.
Pass the ID and the 64-character hexadecimal hash to the widget:
The same fields work in centillionUserConfig. User hashes verify only the ID. They match a contact by External ID, creating an empty contact when none exists. Maintain contact details through Contacts or your CRM integration. Each secret only checks its own kind of signature. A user hash made with the Token secret is refused, and so is a token signed with the User hash secret.

Shopify sign-in

For the Shopify theme embed, open Channels → Shopify and choose Prepare customer sign-in. Shopify signs the customer’s store identity and the embed refreshes its short-lived token automatically. This preserves existing identity secrets. Typing an email in chat does not sign a shopper in.

Website events

The current embed also supports event listeners through window.Centillion.addEventListener or window.centillion.addEventListener. These share the same listener registry. A sign-out or visitor change clears the conversation and stops events from its pending replies. Runtime display options do not verify a customer’s identity.

Connecting website and WhatsApp support

Use one stable customer ID as the Contact’s External ID, and store the customer’s phone number on that same Contact. A signed website identity uses that customer ID. When a WhatsApp conversation becomes a Helpdesk ticket, the sender’s phone number can reuse the existing Contact, preserving its External ID and linking the customer’s tickets across channels. Phone matching uses an international number including its country code. If multiple Contacts already have that number, correct the duplicate records before linking the conversation. Helpdesk does not choose one or merge them. An anonymous website session stays separate until it has a verified identity. Sharing a Contact lets support staff see related tickets in Customer history when a person takes over from the helpdesk inbox. It does not copy previous website transcripts into a new WhatsApp AI conversation.

Rotating the secrets

Rotate secrets replaces both at once: signatures made with the old ones stop working, and visitors chat anonymously until your server signs with the new ones. Turn off deletes them.

Limits and good to know

  • JWTs must use HS256, and exp, when present, can be at most 24 hours away. Verification allows one minute of clock skew.
  • Public attributes outside the token fit within 1,000 characters of JSON and are visible to the agent.
  • Billing identifiers are never exposed to the agent.
  • The old shared CENTILLION_IDENTITY_SECRET no longer verifies anything.
  • Rotating replaces both secrets at once; until your server signs with the new ones, visitors chat anonymously.

Questions

Should I use a JWT or a user hash?

A JWT for anything new. It supports expiration and updates the contact’s details. User hashes verify only the ID and are kept for existing integrations.

Does the agent see everything in the token?

No. JWT fields are private contact data, available to configured actions. The agent reads only the attributes you select under What the agent may read, plus public attributes passed outside the token.

What happens when a visitor isn’t signed in?

They chat anonymously. Actions that need a verified customer, such as Stripe billing, refuse anonymous visitors.

What happens when my site signs the user out?

Call window.Centillion("resetUser"). It clears the widget identity, public metadata and conversation.

Can a customer prove who they are by typing their email?

No. Only a signature made on your server verifies a visitor. Typing an email in chat, on the website or in Shopify, does not sign anyone in.

What happens if I rotate the secrets?

Both secrets change at once. Signatures made with the old ones stop working, and visitors chat anonymously until your server signs with the new ones.

Try it

Turn on identity verification, sign one test user on your server, and open the widget: the conversation should appear on that user’s contact.

Start free

Start on the Free plan, or take a seven-day trial of a paid plan. Your agent is live on your site in an afternoon.

Book a demo

Fifteen minutes with the team, on your own use case.
Or ask the assistant on this page.

What Centillion is

How the agent, its knowledge and its channels fit together.

Stripe billing

Show signed-in customers their invoices and subscriptions in chat.

Website widget

Install the chat widget the identity is passed to.
Last modified on October 20, 2026