Skip to content

Auth & sessions

The SDK never authenticates the user itself. Your app has already signed the user in; you mint a short-lived session JWT and pass it as sessionToken.

Minting the token (server-side)

Sign a JWT with the same JWT_SECRET the AW Chat backend uses. The only required claim is the user id — as userId (or sub):

ts
import jwt from "jsonwebtoken";

const token = jwt.sign(
  { userId: user.id },
  process.env.JWT_SECRET,        // must match the backend's JWT_SECRET
  { expiresIn: "1h" },           // keep it short-lived
);

Send token to the client and pass it to <AWChat sessionToken={token} />.

Never sign on the client

JWT_SECRET is a server secret. Mint tokens on your backend and deliver them to the app — never embed the secret in client code.

How the backend validates it

Every /api/* request must carry Authorization: Bearer <token>. The backend:

  1. Verifies the signature against JWT_SECRET.
  2. Reads userId (falls back to sub).
  3. Resolves it to an Intercom contact (cached in user_contacts).

Invalid/expired/missing → 401.

Handling expiry

When the backend returns 401, the SDK calls onSessionExpired and shows a "session expired" panel. Refresh the token and re-mount (or update the sessionToken prop):

tsx
<AWChat
  sessionToken={token}
  onSessionExpired={async () => {
    const fresh = await refreshSupportToken();
    setToken(fresh);
  }}
  /* … */
/>

Token contents

  • Required: userId or sub.
  • Recommended: exp (short TTL, e.g. 1h).
  • Audience/issuer claims are not validated today; keep the secret strong and the TTL short.

AW Chat SDK — internal integration docs.