Identity Verification
Use identity verification to secure your chat from user impersonation
This step is optional but strongly recommended before you're ready for live production chats. Identity Verification ensures bad actors can't impersonate your customers to see their issues and conversations.
This is done by adding a verification for the identity of the user sending a message through the chat widget, to prevent your customers from manually changing their email in the frontend to impersonate each other.
Pylon is not unique on this front - because a user's identity in the chat is determined client-side, any chat is susceptible to users spoofing their email.
HMAC Email Hash
Generate an Identity Secret
Starting from your Chat Widgets page (EU), navigating to your Chat Widget's Settings tab. In the "Identity Verification Secret" section, select the "HMAC email hash" option and then click "Generate Secret" if a secret hasn't been generated yet. This will be the only time you will see this key. Save the key somewhere safe, such as a password manager. If you lose your key, you’ll need to regenerate it and replace the key later. Save the changes to your chat widget.
Setup Backend
In your backend, hash the user’s email address using HMAC-SHA256 with the secret you just generated. Note that the secret is a hex string and must be decoded to text before use.
Here are some code snippets to help:
const { createHmac } = require("node:crypto");
const secret = "GENERATED_IDENTITY_SECRET";
const email = "CHAT_USER_EMAIL";
const secretBytes = Buffer.from(secret, "hex");
const verificationHash = createHmac("sha256", secretBytes)
.update(email)
.digest("hex");import hmac
import hashlib
def sign_message_with_hmac(message, secret):
secret_bytes = bytes.fromhex(secret)
signature = hmac.new(secret_bytes, message.encode(), hashlib.sha256).hexdigest()
return signaturepackage auth
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
)
func SignMessageWithHMAC(message, secret string) (*string, error) {
secretBytes, err := hex.DecodeString(secret)
if err != nil {
return nil, errors.New("unable to decode secret")
}
h := hmac.New(sha256.New, secretBytes)
h.Write([]byte(message))
signature := h.Sum(nil)
signedMsg := hex.EncodeToString(signature)
return &signedMsg, nil
}Send this hash to the Frontend and set it on the window object:
JSON Web Token (JWT)
Generate an Identity Secret
Starting from your Chat Widgets page (EU), navigating to your Chat Widget's Settings tab. In the "Identity Verification Secret" section, select the "JWT (signed token)" option and then click "Generate Secret" if a secret hasn't been generated yet. This will be the only time you will see this key. Save the key somewhere safe, such as a password manager. If you lose your key, you’ll need to regenerate it and replace the key later. Save the changes to your chat widget.
Setup Backend
Generate a short-lived JWT for each authenticated user from your backend. Never expose the shared secret or generate JWTs in browser code.
Sign the JWT using HS256 and the generated secret exactly as displayed. Unlike the HMAC secret, the JWT secret must not be hex-decoded.
Include these claims:
email: The authenticated user’s email address.aud: Your Chat Widget App ID.iat: The token’s issuance time.exp: The expiration time. Tokens may last at most 15 minutes; we recommend 10 minutes.
Optional identity claims include
name,account_id,account_external_id,contact_id, andcontact_external_id. Any identity values supplied to the widget must match those signed into the JWT.Return the JWT to your frontend and pass it to the chat widget using the
jwtfield in the next step. Here are some code snippets to help:
Send the JWT to the Frontend and set it on the window object:
Generate a fresh JWT whenever the chat widget is initialized or the authenticated user changes. If you were using an email hash before with HMAC, then omit
email_hashwhen using JWT authentication.
Last updated
Was this helpful?

