Skip to content

Identity verification ​

If your site has accounts, the chat can know who it is talking to. Your page passes the user's id, name and email, plus a hash your server computes with a secret only it and the chat server know. With a valid hash the visitor is verified: the agent and your team can trust the details, and the user's conversations follow them from device to device.

1. Get the identity secret ​

In the admin panel, open the bot's Security tab and create an identity secret. It starts with wfs_ and is shown once: store it on your server (an environment variable such as WIREFACE_IDENTITY_SECRET), never in a page. Making a new one replaces the old one, and hashes made with the old one stop working. (The REST API's POST /api/v1/bots/{id}/identity-secret does the same.)

Then choose the identity mode (security.identity.mode):

ModeWhat happens
off (default)The page's user is ignored.
optionalVisitors may be anonymous. A user with a valid hash is verified; one without a hash is kept but marked unverified; one with a wrong hash is ignored (identity_invalid).
requiredEvery visitor needs a valid hash. With no user the chat refuses to connect (identity_required); with a hash that doesn't match, too (identity_invalid). Make sure the bot has a secret first.

Publish the bot after changing either.

2. Compute the hash on your server ​

The hash is HMAC-SHA256(identity secret, user id), written as lowercase hex. The user id is whatever string you pass as user.id (up to 200 characters).

js
import { createHmac } from 'node:crypto';

export function wirefaceHash(userId) {
  return createHmac('sha256', process.env.WIREFACE_IDENTITY_SECRET).update(String(userId)).digest('hex');
}
python
import hashlib
import hmac
import os

def wireface_hash(user_id):
    secret = os.environ["WIREFACE_IDENTITY_SECRET"].encode()
    return hmac.new(secret, str(user_id).encode(), hashlib.sha256).hexdigest()
php
<?php
function wireface_hash($userId) {
    return hash_hmac('sha256', (string) $userId, getenv('WIREFACE_IDENTITY_SECRET'));
}
go
package chat

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"os"
)

func WirefaceHash(userID string) string {
	mac := hmac.New(sha256.New, []byte(os.Getenv("WIREFACE_IDENTITY_SECRET")))
	mac.Write([]byte(userID))
	return hex.EncodeToString(mac.Sum(nil))
}

3. Pass it to the chat ​

Render the user into the page with the hash. With the script tag, set window.wirefaceChatSettings before widget.js loads:

html
<script>
  window.wirefaceChatSettings = {
    bot: 'pk_your_bot_id',
    user: {
      id: '42',
      hash: 'the hex your server computed for 42',
      name: 'Ana Silva',
      email: 'ana@example.com',
    },
  };
</script>
<script src="https://chat.example.com/widget.js" async></script>

With JavaScript or the npm package, pass user to boot(), bootWirefaceChat() or the React component. Escape the values properly when you write them into HTML (a JSON encoder that escapes < does it).

attributes takes more facts to keep with the visitor (plan, company and so on). The full shape is in the JavaScript API.

examples/identity-node/ in the repo is a small Node server that signs a user in and renders the page with the hash (run it with WIREFACE_HOST, WIREFACE_BOT and IDENTITY_SECRET set).

Signing in and out ​

  • Signing in on a page that already has the chat: call identify({ id, hash, name, email }). The details apply straight away. The rest of the user's history (below) joins the chat when it next connects, for example on the next page.
  • Signing out: call WirefaceChat.shutdown({ forget: true }). It removes the chat and deletes the visitor token and conversation it kept in your site's storage, so the next person on that browser starts fresh. Boot it again afterwards if the chat should stay on the page for anonymous visitors (the React component starts a new chat by itself the next time it mounts).

The server protects signed-in users even if a page gets this wrong:

  • A visitor token that belongs to a verified user only carries on for that same user, with a valid hash. After sign-out (no user), or when a different user signs in on the same browser, the server starts a fresh visitor, so nobody sees the previous user's conversations.
  • Signing a different user in with identify() while a verified user has the chat is refused with identity_invalid. Call shutdown({ forget: true }) on sign-out, then boot again.

What verification gets you ​

  • Conversations follow the user. When a verified user connects, the server picks up their earlier visitor record: their conversations carry on across devices and sign-outs. Anything they did anonymously in that browser before signing in moves into their history.
  • The agent knows who it is talking to. It is told the visitor's name and email, marked as verified or not. In the bot's instructions and guardrails, {{visitor.name}} and {{visitor.email}} are filled in for verified visitors only (otherwise they are empty), alongside {{page.url}} (origin and path, no query string), {{page.title}}, {{agent.name}}, {{agent.role}} and {{business.name}}.
  • Your team sees the user in the admin panel, and you can find their data by your own id for data requests (GET /api/v1/visitors?userId=42, see Privacy).
  • HTTP tools can use it: {{visitor.userId}} and {{visitor.email}} (filled in for verified visitors only) and {{visitor.verified}} in a tool's request. See Tools and MCP.

Unverified identities

In optional mode a user without a hash is accepted as given, so a visitor can claim any id or name. The agent is told the details are unverified, and HTTP tools only get {{visitor.userId}} and {{visitor.email}} for verified visitors ({{visitor.verified}} says which). Don't let the agent act on an account based on what an unverified visitor says.

Problems ​

  • identity_required: the bot requires identity and the page sent no user at all.
  • identity_invalid: the hash doesn't match (in required mode the chat then refuses to connect; in optional mode it carries on anonymously), or a different user tried to take over a signed-in chat.

Check that you hash exactly the string you pass as id (42 and "42 " differ) and that you use the current secret. Upper- and lowercase hex both work. See Errors.

Wireface Chat 0.1.0. These docs are served by your own server.