Skip to main content
Verifying users means that your server signs each signed-in user’s id into a user token, which proves to HelpAlive who that user is. This page shows your developer how. It is optional and recommended. It is complete on its own, so an AI coding agent can follow it without reading any other page. Without it, HelpAlive trusts the user id your page sends. This means that someone who edits the page in their browser could send another user’s id and read that user’s chats. With it, your server signs each id. Once you turn on Only allow verified users, nobody can pretend to be someone else. Add it before you open the agent to all your users.

User verification at a glance

  • Your server signs a user token with HS256, keyed on the text of your signing secret.
  • Your page passes the token to identify() as userToken, in place of userId and tenantId.
  • The secret stays on your server, out of your pages, your repository and any prompt for an AI coding agent.
  • Once you turn on Only allow verified users, HelpAlive refuses every request without a valid user token.
  • Setup takes your developer about 15 minutes, and everything is also on Settings → Setup & API Key, step Verify your users.

Prerequisites

  • HelpAlive is installed and your pages call identify(). See Install the script.
  • A server that knows who is signed in.
  • Your developer, about 15 minutes.

The rules

  1. Sign the token on your server, never in the browser.
  2. Sign it with HS256, keyed on the text of your signing secret.
  3. Put the same id your page passes as userId in sub, as a string.
  4. Put the same id your page passes as tenantId in tenant, as a string. Leave tenant out if your app has no companies or workspaces.
  5. Don’t add exp, kid or any other claim.
  6. Send the token only to the signed-in user’s own page, with Cache-Control: no-store.
  7. Pass the token to identify() as userToken, in place of userId and tenantId.
  8. Keep the secret out of your pages, your repository and any prompt for an AI coding agent.
  9. Keep reset() in your logout code, apart from identify(), as before.

How to set up user verification

1

Create your signing secret

On Settings → Setup & API Key, step Verify your users, click Create your signing secret. Keep it on your server, like a password, wherever you keep other secrets. The code below reads it from HELPALIVE_SIGNING_SECRET; the name is up to you.
2

Make a user token on your server

Where your server knows the signed-in user, add these lines. They make the user token, which refers to a short signed text that says who the user is. user stands for your app’s signed-in user.
On a CommonJS server, write const jwt = require("jsonwebtoken") in place of the import line.
The token is a JWT signed with HS256, keyed on the text of your secret:Leave out an expiry (exp) and a key id (kid). HelpAlive honors an exp if you add one, but a token that expires stops working in a tab left open. Rotating the secret is how you cut old tokens off.
3

Get the token to the page

Send the token only to the page of the user it names. Print it into the page from your server template, or add it to an endpoint your app already has for the current user. Send that response with Cache-Control: no-store.
4

Pass the token to identify()

Replace your identify() call with this one. The token says who the user is and which company they belong to, so you no longer pass userId or tenantId.
If you still pass a userId or tenantId that differs from the token, the token wins and the browser console shows a warning. A value that isn’t a JWT is ignored, with an error in the console. That catches the secret pasted in by mistake.Your logout code doesn’t change. Keep reset() there, apart from identify(), never straight after it:
reset() also drops the token, so the next user on the same browser never inherits it.
5

Add the secret to your environment

Add HELPALIVE_SIGNING_SECRET to your server’s environment, with the secret from step 1 as its value. If your project keeps a list of variables, such as .env.example, add the name there with no value.

With Google Tag Manager

If you installed HelpAlive with Google Tag Manager, pass the token through the data layer. Create a Data Layer Variable named helpalive_user_token, then add these lines:

With an AI coding agent

The Verify your users step has a prompt for Claude Code, Codex, Cursor or GitHub Copilot under With an AI coding agent. It makes the token on your server, passes it to identify(), and lists HELPALIVE_SIGNING_SECRET with no value. You set the value yourself, so the secret never goes into a prompt. The prompt is also on Install with an AI coding agent.

Check it works

  1. Deploy your change, sign in to your app and open the agent.
  2. On Settings → Setup & API Key, step Verify your users, press refresh on Check your setup. It looks for a verified sign-in in the last 30 minutes. Your signing works means that it found one.
  3. The Verified sign-ins, last 7 days card shows the share of sign-ins that arrived verified.
If tokens arrive but fail, the card says how many and what to fix:

Only allow verified users

Until you turn this on, everyone can see the agent. Turn it on once every page that calls identify() sends a token.
1

Wait for verified sign-ins

The switch unlocks once verified sign-ins arrive. It turns on only after a verified sign-in in the last 30 minutes, so sign in to your app and open the agent first.
2

Turn on Only allow verified users

It sits under the Verified sign-ins, last 7 days card. Recommended on the switch means that nearly all sign-ins are verified. The switch also says how many sign-ins it would have refused in the last 7 days.
3

Confirm

It asks first: “Hide the agent from anyone we can’t verify?” The dialog says how many people in the last 7 days had no token, or a token that had expired or didn’t check out. Press Turn it on anyway, or Show me the fix to open the setup instructions instead.
With it on, HelpAlive refuses every request without a valid user token:
  • A page without a valid token gets no chat button, so the user doesn’t see the agent.
  • If a token expires while the chat is open, HelpAlive calls your refreshUserToken function, if you pass one to identify(), and sends the request again. If that fails, the user sees “Your session needs a refresh. Reload the page to keep chatting.” with a Reload page button.
  • If an open chat is refused for any other reason, the question box gives way to “Chat isn’t available right now. Please try again later.” A running assist stops quietly.
  • Activity from pages without a token is refused too. Those users stop showing in Reports, Audience and the setup steps.
While the switch hides the agent from people, step 4 on Settings → Setup & API Key says how many couldn’t see it in the last 7 days, the main reason, and the fix. We also email your team when it starts. See Setup & API Key. You can turn it off at any time, and requests without a token are served again.

How to rotate the secret

Click Rotate next to your secret and put the new one in HELPALIVE_SIGNING_SECRET on your server. Nothing in your code changes. The previous secret keeps working until you rotate again, so nobody is refused while you roll it out. If a secret leaked, rotate once more after your server uses the new one, and the leaked one stops working. Then put that newest secret on your server too, or the next rotation will cut your server off.

Why does the card say no verified sign-in when the server signs tokens?

The check moves only when the agent is used. Sign in, open the agent, and press refresh. Then check that the page passes userToken to identify(), and that the response carrying it isn’t cached.

Why don’t some users see the chat button?

Some users don’t see the chat button because Only allow verified users is on, and their page sent no valid token. Step 4 on Settings → Setup & API Key names the main reason and the fix. Check that every page that calls identify() sends a token, or turn the switch off while you fix it.

Why do users see Your session needs a refresh?

Users see “Your session needs a refresh” because their token expired and could not be renewed. Pass refreshUserToken to identify() so HelpAlive can get a fresh one, or leave the expiry out of the token.

Why does the console say userToken is not a JWT?

The console says this when the page passed something other than a signed token, often the secret itself. Pass the token your server made, and rotate the secret if it reached a page.

Next

Identify users

Every identify() field.

Security overview

Public keys, secret keys and sessions.

Troubleshooting

The failures that show no error.
Last modified on October 11, 2026