v1.2.0

OAuth install handshake

Express server that handles ONAPPINSTALL / ONAPPUPDATE / ONAPPUNINSTALL events for a Bitrix24 marketplace app, persists tokens per portal, and builds a B24OAuth client on demand with a refresh callback wired to storage.

What it does

This is the missing piece between "I have a clientId/clientSecret" and "I have a working B24OAuth client". An OAuth-installed Bitrix24 app receives ONAPPINSTALL, ONAPPUPDATE, and ONAPPUNINSTALL events to your configured handler URL. This recipe:

  1. Receives the install event and persists the OAuth tokens per portal (member_id as the key).
  2. Exposes clientForMember(memberId) — builds a B24OAuth instance from stored tokens, attaches a refresh callback so the next refreshed pair is written back to storage automatically.
  3. Removes credentials on uninstall.
  4. Demonstrates a per-portal REST call (profile) through the resulting client.

Use this as the scaffold for a multi-tenant backend that serves many Bitrix24 portals from one OAuth app.

Stack

Node.js 18+, express.

Install

pnpm add express

Environment

export PORT=3001                             # default
export B24_CLIENT_ID='local.abc123'          # from your Bitrix24 dev console
export B24_CLIENT_SECRET='...'

In the Bitrix24 dev console:

  • Install handler URL: https://your-server.example.com/install
  • Uninstall handler URL: https://your-server.example.com/uninstall

For local development, expose with npx ngrok http 3001.

Run

npx tsx 12-oauth-install.ts

Then trigger the handshake by installing the app on a Bitrix24 portal. Verify with:

curl https://your-server.example.com/portal/<memberId>/profile

Source

skills/b24jssdk-recipes/examples/12-oauth-install.ts.

Notes

  • Persistence is a JSON file for demo purposes (.oauth-store.json). Replace with Postgres / Redis / your real datastore for production.
  • application_token — Bitrix24 sends this with both install and uninstall events. The recipe stores it but does not verify it on uninstall — in production, compare the value before removing credentials to protect against spoofed uninstall calls.
  • setCallbackRefreshAuth is wired at every clientForMember() call. This ensures the storage always has the latest token pair after the SDK auto-refreshes a 401.
  • Always return 200 to the install / uninstall endpoints. Non-2xx triggers Bitrix24 retries for 24 hours.
  • For multiple workers serving the same portal, use a transactional store (Postgres ON CONFLICT UPDATE) so concurrent refreshes don't lose tokens.
  • For the wider per-portal multi-tenant pattern (cache strategy, lifecycle, revoked installs), this recipe is the foundation — wrap clientForMember in an LRU cache keyed by memberId for hot portals.