SDK · Growth+

Custom OAuth providers

Register OAuth apps Leash hasn't pre-built — Slack, Notion, custom OIDC, your company's SSO, anything with a standard OAuth 2.0 flow. Apps in your org get a fresh access token through one SDK call. client_secret stays out of your app code.

1. Register the provider (once, on the dashboard)

On the org page, the “Custom OAuth providers” card walks you through:

  • A slug (used by your app to refer to it: slack, notion, …)
  • Display name and OAuth authorize / token URLs
  • Default scopes
  • Your client_id and client_secret — encrypted with your org's KMS key before storage

Reserved slugs (gmail, google_calendar, google_drive, etc.) are taken — they map to built-in providers.

2. Send users through the OAuth flow

Same as built-in providers — redirect to Leash's connect endpoint with the slug; Leash handles the OAuth round-trip and stores the user's tokens.

// In your app, redirect the user to:
const url = client.getConnectUrl('slack', '/post-connect-page')
// e.g. <a href={url}>Connect Slack</a>

3. Get the user's access token in your app

Once the user has connected, every app in your org can pull a fresh access token to call the third-party API directly. Refresh-on-expiry happens transparently on the platform side — no per-app handler.

const slackToken = await client.getAccessToken('slack')
await fetch('https://slack.com/api/chat.postMessage', {
method: 'POST',
headers: {
Authorization: `Bearer ${slackToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ channel: '#general', text: 'hello' }),
})

Failure modes

  • not_connected — the user hasn't authorized this provider yet. Send them through the connect flow (step 2). The error includes a connectUrl you can redirect to.
  • token_expired — refresh failed (the user revoked access, or the upstream provider rotated something). Treat the same as not_connected.
  • upgrade_required — registering custom OAuth providers requires the Growth plan. Built-in providers (Gmail, Calendar, Drive) work on every plan.