Skip to content

Identity token format and exchange

Use your own identity provider when your app already knows who is reviewing. Your backend signs a short-lived JWT, and the browser passes it to Gutternote.

This option needs the Bikeshed plan. A workspace owner can upgrade in Billing.

Project configuration

On the project’s Configure page, under Who may comment, choose Your own identity provider.

  • Issuer is optional. When set, the token’s iss must match it exactly.
  • Max token age is 1 to 60 minutes. Default: 5.
  • The project needs a signing secret. Gutternote provisions it. To get one, contact us. Do not switch a live project until the secret is in place.

JWT claims

Sign with HS256 and the project’s signing secret.

ClaimRequiredDescription
subyesStable user ID in your app.
expyesUnix time after which the token is refused.
iatrecommendedUnix time used for the max token age. More than 2 minutes in the future is refused.
isswhen configuredMust match the project’s issuer.
namenoDisplay name, visible to everyone who can read threads. Falls back to sub, never to email.
emailnoStored in lowercase. Used for domain-based agent access, and for member access when email_verified is true.
email_verifiedfor member accesstrue only when your app has confirmed the person owns email.
picturenoAvatar URL. Your CSP must allow its origin.
{
"iss": "https://id.acme.com",
"sub": "user_123",
"name": "Dana Reed",
"email": "dana@acme.com",
"email_verified": true,
"iat": 1789991700,
"exp": 1789992000
}

Sign tokens on your server. Never put the signing secret in browser code, a client-side environment variable or the page source.

Member access

A token lets a person sign in, comment and reply. Triage, resolve, stopping a task and sending work to agents also need a workspace member. Gutternote matches the token’s email to a member only when email_verified is true.

Set email_verified only for an address your app has confirmed. If your sign-up never checks addresses, leave it out. Otherwise anyone who types a teammate’s address gets that teammate’s member access. Without it, the person can still comment. The server refuses member operations with 403 member_required.

Session lifetime

A session from a token lasts 12 hours, or the project’s session length if that is shorter. It is never renewed. The widget asks your backend for a new token instead. A change to email_verified applies from the next exchange.

Exchange through the widget

Pass the token:

await Gutternote.init({
key: 'pk_live_...',
identityToken: await myBackend.gutternoteToken(),
})

Or give a same-origin endpoint:

await Gutternote.init({
key: 'pk_live_...',
authEndpoint: '/api/gutternote-token',
})

The widget calls authEndpoint with credentials and expects { "token": "eyJ..." }. It calls it only when the project requires your identity provider. If the call fails, the widget stays readable and uses no other identity.

Exchange through the HTTP API

POST /v1/sessions/token
Gutternote-Key: pk_live_...
Origin: https://preview.acme.com
Content-Type: application/json
{ "token": "eyJ..." }

It returns 201 with a session. Errors are in Errors.