Integrate

Keeping users signed in

Refreshing access tokens, signing out, listing a user's devices, and when sessions end on their own.

Where to keep the tokens

Keep the refresh token server-side, or in an HttpOnly; Secure; SameSite=Lax cookie. Never in localStorage, where any script on your page can read it.

Refreshing

When the access token expires (or about a minute before), POST /v1/oauth/refresh-token { appId, refreshToken } → a new { accessToken, refreshToken }.

ts
const next = await identise<{ accessToken: string; refreshToken: string }>("/v1/oauth/refresh-token", { refreshToken });
await saveTokens(next); // store the NEW refresh token: the old one has been replaced
Store the new refresh token every time: the old one is replaced. Two refreshes with the same token within a few minutes get the same answer, so requests running in parallel don't sign the user out.

When a session ends

401 Token.InvalidOrExpired on a refresh means the session is over: send the user to sign in. Sessions also end on their own, within a few seconds, when:

  • the user's password is changed or reset;
  • their account is deleted;
  • they disconnect your app;
  • they go over your app's session limit (the oldest sessions go first).

Access tokens already issued stay valid until they expire, at most your app's access token lifespan later (15 minutes unless you changed it). A suspended user can't refresh: 403 User.Suspended.

Signing out

POST /v1/oauth/logout { refreshToken } → 204, with your app's own API key: it ends only your app's sessions, and an unknown token gets the same 204.

A user's devices

  • GET /v1/oauth/sessions?appId=…&email=…&currentToken=<refresh token>&page=1&pageSize=10 lists them; isCurrentSession marks the one currentToken belongs to.
  • DELETE /v1/oauth/sessions/{sessionId}?appId=…&email=… signs one out.

Each item is { id, deviceName, browser, os, ipAddress, isCurrentSession, lastActive, startedAt, appName }.