Skip to main content
When your app runs inside the Salesive dashboard, its front end can ask the dashboard for a session token: a short lived JWT, signed by Salesive, that names the store and the signed in user. Your front end sends it to your own backend, and your backend verifies it. This is the reliable way to know who is calling. The ?shop= and ?user= launch parameters are convenient, but anyone can type them into a URL. With token exchange, your backend can also trade a session token for a normal app access token. An embedded app then needs no OAuth redirect inside the iframe at all.

How it fits together

  1. Your front end calls getSessionToken() from the App Bridge.
  2. The dashboard asks the Salesive API to mint a token for your installation and the signed in merchant, and posts it back to your iframe.
  3. Your front end sends it on each request: Authorization: Bearer <token>.
  4. Your backend verifies it with the Salesive public key and reads the store from dest.
  5. Optional: the first time your backend sees a store it holds no access token for, it trades the session token for one (token exchange).

Get a token in the front end

Tokens last 60 seconds. The bridge caches the current token and fetches a new one about 10 seconds before it expires, so call getSessionToken() before every request rather than storing the token yourself. getSessionToken({ timeoutMs, forceRefresh }) rejects with a SessionTokenError whose code is: The cached token is dropped when the merchant logs out or switches store.

Token format

The token is a compact JWS signed with ES256 (ECDSA P-256, SHA-256).

Verify a token on your backend

Fetch the public key set once and cache it:
Then, for every request:
  1. Split the token into header, payload and signature.
  2. Require alg to be ES256. Never let the token choose the algorithm.
  3. Find the key whose kid matches. If none does, refetch the key set once (Salesive may have rotated its key), then give up.
  4. Verify the signature over header.payload.
  5. Require aud to equal your client id. Salesive signs every app’s tokens with the same key, so skipping this check would let another app’s token into your backend.
  6. Require iss to equal the Salesive API base you call.
  7. Check exp and nbf, allowing at most a few seconds of clock drift.
  8. Require purpose to be session.
A dependency free Node verifier (this is what the app starter ships in server/sessionToken.js):
Any standard JWT library works too, for example jose:
A session token proves who is calling. It does not carry API access. To call the Salesive API, use your app access token (from the install flow or token exchange below).

Token exchange: install without the redirect

The merchant already approved your app’s scopes when they installed it from the marketplace. Token exchange lets your backend turn a session token into an app access token for that installation, without sending the merchant through the consent redirect again inside the iframe.
The response is the same token pair the redirect install returns, so refresh and revoke work as usual. The exchange is refused (400 or 401) when:
  • the client secret is wrong or missing (exchange is for confidential clients only),
  • the token was issued for another app (aud), has expired, or was already exchanged (jti),
  • the app is no longer installed on that store.
Good practice:
  • Exchange once per store, then refresh. Store the access and refresh tokens and only exchange when you hold none for the store (first open, or after an uninstall and reinstall). Every exchange issues a new token pair.
  • Use a fresh token for the exchange (getSessionToken({ forceRefresh: true })), since a token can be exchanged only once.
  • The access token acts for the store, with the scopes granted at install. It is not tied to the user in sub; use sub and role for your own user model.

Security notes

  • The token is delivered only to your app’s origin (the dashboard posts it to the origin of your appUrl), and lives 60 seconds.
  • Never log full tokens, and never put them in URLs you control.
  • Keep using the ?shop= parameter only as a hint for which store to show first. Decide access from dest.

Next steps

App Bridge

The full bridge reference, including getSessionToken.

App starter

A working app with the verifier and the exchange wired in.