Guides
Identify users
Sign in your users in the widget, so their conversations follow them and agents see who they are.
How it works
Section titled “How it works”// token: an identity token that your server signed for the signed-in userIris.identify({ token });- Your server signs an identity token with your identity secret.
- Your page passes the token to the widget with
Iris.identify. - Iris checks the signature and links the contact to your user’s
sub. Earlier anonymous conversations move to that contact.
Get the identity secret
Section titled “Get the identity secret”An admin copies the identity secret from Settings → Install in the dashboard. Only admins see it. Store it in your server’s environment as IRIS_IDENTITY_SECRET.
IRIS_IDENTITY_SECRET=<your identity secret>Sign an identity token on your server
Section titled “Sign an identity token on your server”Sign a new identity token on each page load, or cache it until it nears exp. Every claim is in Identity token claims.
import { SignJWT } from "jose";
// user is the signed-in user in your product.const token = await new SignJWT({ email: user.email, name: user.name, attributes: { plan: user.plan, role: user.role },}) .setProtectedHeader({ alg: "HS256", typ: "JWT" }) .setSubject(user.id) .setExpirationTime("1h") .sign(new TextEncoder().encode(process.env.IRIS_IDENTITY_SECRET));import osfrom datetime import datetime, timedelta, timezone
import jwt
# user is the signed-in user in your product.token = jwt.encode( { "sub": user.id, "email": user.email, "name": user.name, "attributes": {"plan": user.plan, "role": user.role}, "exp": datetime.now(timezone.utc) + timedelta(hours=1), }, os.environ["IRIS_IDENTITY_SECRET"], algorithm="HS256",)Pass it to the widget
Section titled “Pass it to the widget”Call Iris.identify after Iris.init. Call it again with a new token before the old one expires. Call Iris.logout when the user signs out.
// After the user signs inconst { token } = await fetch("/api/iris-token").then((res) => res.json());Iris.identify({ token });
// When the user signs outIris.logout();Check your code with the test token
Section titled “Check your code with the test token”Show the test tokenHide the test token
Sign these claims with this identity secret. Your code must print exactly this identity token. If it does not, compare the header and the order of the claims.
7c1e4b9a2f6d0e8c3b5a1f9d7e2c4a6b8d0f3e5c7a9b1d2e4f6a8c0e2b4d6f8a{ "sub": "user_8421", "email": "maria@example.com", "name": "Maria Lopez", "attributes": { "plan": "pro", "seats": 12 }, "exp": 1893456000}import { SignJWT } from "jose";
const secret = new TextEncoder().encode("7c1e4b9a2f6d0e8c3b5a1f9d7e2c4a6b8d0f3e5c7a9b1d2e4f6a8c0e2b4d6f8a");
const token = await new SignJWT({ "sub": "user_8421", "email": "maria@example.com", "name": "Maria Lopez", "attributes": { "plan": "pro", "seats": 12 }, "exp": 1893456000}) .setProtectedHeader({ alg: "HS256", typ: "JWT" }) .sign(secret);
console.log(token);import jwt
token = jwt.encode( { "sub": "user_8421", "email": "maria@example.com", "name": "Maria Lopez", "attributes": { "plan": "pro", "seats": 12 }, "exp": 1893456000 }, "7c1e4b9a2f6d0e8c3b5a1f9d7e2c4a6b8d0f3e5c7a9b1d2e4f6a8c0e2b4d6f8a", algorithm="HS256",)
print(token)eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyXzg0MjEiLCJlbWFpbCI6Im1hcmlhQGV4YW1wbGUuY29tIiwibmFtZSI6Ik1hcmlhIExvcGV6IiwiYXR0cmlidXRlcyI6eyJwbGFuIjoicHJvIiwic2VhdHMiOjEyfSwiZXhwIjoxODkzNDU2MDAwfQ.0RrzrVC8W-h9B_rrS9KlmwI67hD1bmMnTeaPesGUUmoThen sign in to your product, open the widget and send a message. In the dashboard inbox, the conversation shows the contact’s name and email.
Expiry and secret rotation
Section titled “Expiry and secret rotation”- An identity token stops working at its
exp. After that, the session request fails with401. - When an admin rotates the identity secret, every token signed with the old secret fails at once. Put the new secret in
IRIS_IDENTITY_SECRETand deploy your server right after.
Fix common problems
Section titled “Fix common problems”| Message | What happened | Fix |
|---|---|---|
Iris: <method> ran before Iris.init, so nothing changed.# | identify, logout or update ran before Iris.init. After an early identify, the contact stays anonymous. | Call Iris.init({ appId }) first. Calls made before iris.js loads wait in a queue, in order. |
Iris: identify got no identity token, so the contact stays anonymous.# | The token is empty or not a string. Often your token endpoint failed. | Check that your server returns an identity token, then pass it as Iris.identify({ token }). |
401 on the session request# | Iris rejected the identity token. It expired, its signature does not match the identity secret, or sub or exp is missing. The console shows Iris: <action> failed, because Iris rejected the identity token. | Sign a new identity token with the current identity secret and both required claims. Check your code with the test token. |