Identity verification for the messenger
How OctaDezx identity verification works: a short-lived HS256 user token signed on your server proves a signed-in user to the messenger, unlocking their own orders, attributes and push. Available at version 0.1.
Status: available (v0.1). Messenger SDKs run on the customer's device, so anything they say about who the user is can be edited. OctaDezx identity verification lets your server prove a signed-in user with the business's identity secret. The recommended proof is a user token: an HS256 JWT with the user id, an issue time and an expiry of at most 24 hours, optionally carrying a verified email. The SDKs refresh it before it expires. An older user hash, an HMAC of the user id that never expires, is still accepted unless the business requires tokens. OctaDezx verifies either inside the database, where the secret is stored encrypted, so the secret never reaches the device. A verified user can ask about their own orders and bookings and can store attributes, events and push tokens; anyone else stays anonymous. Identity verification, with both tokens and hashes, is available at version 0.1, and signUserToken ships in @octadezx/sdk.
How it works
- OctaDezx issues your business an identity secret (odxis_...). It lives on your server only.
- When a signed-in user loads your site or app, your server signs a user token: an HS256 JWT with sub (the user id), iat and exp, at most 24 hours long, optionally with email, name and attributes.
- You pass it to the messenger as userJwt, with a refreshToken callback that fetches a new one. The SDK refreshes a minute before expiry without signing the user out.
- OctaDezx verifies the token inside the database: exactly HS256, the signature first, then the claims, with 60 seconds of clock skew. The secret never travels to the edge function or the device.
Token
header { "alg": "HS256", "typ": "JWT" }
payload { "sub": "u_123", "iat": 1793786400, "exp": 1793790000, "email": "jo@example.com" }
signed HMAC-SHA256( key = utf8(identity secret), message = base64url(header) + "." + base64url(payload) )What verification changes
A browser that only types an email into the chat stays anonymous, whatever it typed. This is enforced in the database, not in the client. WhatsApp, Instagram, Messenger, email, voice and the server Agent API are unaffected, because those identities come from a platform or from your server.
| Anonymous (no proof, or a wrong or expired one) | Verified | |
|---|---|---|
| Chat | Works normally | Works normally |
| Order and booking lookups | Only those made in this conversation | The user's own orders and bookings, by contact, email or phone |
| Attributes and events | Not stored | Stored on the user's contact |
| Push registration | Refused | Allowed |
| Customer history in replies | Only what this conversation created | The user's |
| Inbox | Anonymous visitor | Linked to the user's contact |
Sign a token and pass it
Node.js
import { signUserToken } from "@octadezx/sdk";
const token = signUserToken(user.id, process.env.OCTADEZX_IDENTITY_SECRET, { ttlSeconds: 3600, email: user.email });Python
from octadezx import sign_user_token
token = sign_user_token(user.id, os.environ["OCTADEZX_IDENTITY_SECRET"], ttl_seconds=3600, email=user.email)Messenger
OctaDezx.boot({ businessId, userJwt: await fetchToken(), refreshToken: fetchToken });Tokens, hashes and requiring tokens
Once all your clients send tokens, switch the business to token_required so a leaked hash is useless. hash_or_token is the default.
| User token (recommended) | User hash (older) | |
|---|---|---|
| Expires | Yes, at most 24 hours after it is issued | Never, until the secret rotates |
| Carries a verified email | Yes | No |
| Accepted when tokens are required | Yes | No |
Rotation and sign out
Rotating creates a new secret and keeps the previous one valid for a grace window, 24 hours by default and up to 168. Tokens and hashes signed with either verify during the window. Deploy the new secret within the window, or revoke the old one immediately after a leak.
Call shutdown() when the user signs out. A conversation bound to one user is never rebound to another, so the next person on the same device starts fresh.
Things to know
- A token or hash is a bearer credential for that user. Serve it only to that user, over HTTPS, and never log it. A token limits a leak to its lifetime, so keep it short and rely on refreshToken.
- Only a token's email claim is verified. An email passed to the messenger any other way is not used to identify anyone.
- Tokens with alg none, any other algorithm, a tampered payload, the wrong secret, an issue time in the future or a lifetime over 24 hours are refused.
- Never ship an odx_ API key in a browser or app.
Install
@octadezx/sdk (available, v0.1.0, MIT license)
Server SDK for Node.js 20 and newer: Agent API with streaming, signed user tokens, webhook verification and devices.
npm install @octadezx/sdk@octadezx/messenger (available, v0.1.0, MIT license)
Web messenger SDK, with React bindings at @octadezx/messenger/react.
npm install @octadezx/messengerQuestions or a larger rollout? Contact us (kevin@octadezx.com).
Frequently asked questions
- Why does an in-app support chat need identity verification? Because the client can be edited. Without a server-signed proof, anyone could type another user's id and ask about their orders. Verification makes the server, not the device, the source of identity.
- What is a user token? An HS256 JWT your server signs with the identity secret, carrying the user id, an issue time and an expiry of at most 24 hours, and optionally a verified email. The server SDKs for Node.js and Python include a signing helper.
- What happens when a token expires? The SDK asks your refreshToken callback for a new one a minute before expiry, and again if the server reports it expired, and swaps it in without signing the user out. A visitor with no valid proof stays anonymous; chat still works.
- Is the older user hash still supported? Yes, unless the business switches to token_required. The hash is an HMAC of the user id and never expires, which is why tokens are recommended.
- Can I rotate the identity secret? Yes. The previous secret stays valid for a grace window of 24 hours by default, or can be revoked immediately.
- Is identity verification available now? Yes, at version 0.1. Sign tokens with signUserToken from @octadezx/sdk on npm, and pass them to @octadezx/messenger or @octadezx/messenger-react-native.