Integrations OAuth Administration Runbook
Tenant-scoped integrations authenticate through the platform OAuth2
authorization-code broker (/api/bots/:bot_id/integrations/oauth/:provider/start
and /callback). The broker never embeds client secrets in code: each branch
supplies its own provider application credentials, stored strictly in Vault.
This runbook is the administrator checklist for enabling a provider family.
1. Register the platform application with the vendor
For every provider family below, create one developer application on the
vendor console. Register the callback exactly as shown, replacing
chat.generalbots.org when operating another domain.
| Family | Vendor console | Callback URL |
|---|---|---|
| HubSpot | app.hubspot.com β App Marketplace β Develop an app | https://chat.generalbots.org/api/bots/*/integrations/oauth/hubspot/callback (register per-bot exact path) |
| Intercom | app.intercom.io β Developer Hub | .../integrations/oauth/intercom/callback |
| Todoist | developer.todoist.com β Apps | .../integrations/oauth/todoist/callback |
| Zoom | marketplace.zoom.us β Server-to-server is NOT used here; build OAuth app | .../integrations/oauth/zoom/callback |
| Notion | notion.so/my-integrations β External OAuth | .../integrations/oauth/notion/callback |
| Google (Drive, Calendar, Sheets, Tasks, Photos, Forms, YouTube Analytics) | console.cloud.google.com β OAuth consent screen + OAuth client (Web) | One client may serve all: .../integrations/oauth/<google_slug>/callback for every slug in use; add scopes listed in Β§3 to the consent screen and mark the app production |
| Microsoft (Outlook, Outlook Calendar, OneDrive, SharePoint) | portal.azure.com β App registrations β Web redirect URI | .../integrations/oauth/<ms_slug>/callback; enable offline_access |
| Meta (Instagram, Facebook Pages) | developers.facebook.com β My Apps β Facebook Login β Settings | .../integrations/oauth/<slug>/callback; one app serves both slugs. Add the Facebook Page and the Instagram Business/Creator account linked to it as app testers while the app is in Development mode |
The botserver builds redirect_uri from the incoming request host, so stage
and production environments are registered separately.
2. Store client credentials in Vault (per branch)
Path contract:
gbo/{org_id}/{branch_id}/{bot_id}/integrations/oauth/{provider}
Keys: client_id, client_secret. Example:
vault kv put secret/gbo/<org>/<branch>/<bot>/integrations/oauth/hubspot \
client_id=<id> client_secret=<secret>
Google/Microsoft families repeat the command once per concrete slug that the
workspace will authorize (google_drive, outlook, β¦). A missing envelope
makes the Authorize button answer HTTP 412 with an explanatory message.
3. Scopes requested by the built-in flow
| Provider | Scope string |
|---|---|
| hubspot | crm.objects.contacts.write crm.objects.deals.read |
| todoist | data:read_write |
| google_drive | https://www.googleapis.com/auth/drive.readonly |
| google_calendar | https://www.googleapis.com/auth/calendar.events |
| google_photos | https://www.googleapis.com/auth/photoslibrary.readonly |
| google_forms | https://www.googleapis.com/auth/forms.body |
| youtube_analytics | https://www.googleapis.com/auth/yt-analytics.readonly |
| outlook / outlook_calendar / onedrive / sharepoint | offline_access https://graph.microsoft.com/.default |
instagram_basic,instagram_content_publish,pages_show_list,pages_read_engagement,business_management | |
| facebook_pages | pages_show_list,pages_read_engagement,pages_manage_posts |
Least privilege: request only what enabled actions need; rotate client secrets on the vendor console and update Vault in the same window.
4. Token lifecycle
Access tokens, rotated refresh tokens and expiry are persisted automatically
(token_refresh worker runs hourly and refreshes anything expiring within two
hours). No administrator action is required after initial configuration other
than keeping the Vault envelope current when vendors rotate secrets.
Meta (Instagram, Facebook Pages)
The Meta code exchange answers with a user token that expires in about one
hour, which is far shorter than any publishing workflow. The callback upgrades
it in place with grant_type=fb_exchange_token and stores the resulting
long-lived token (about 60 days); if the upgrade call fails the short-lived
token is kept and the connection simply needs re-authorizing sooner.
Instagram publishing additionally requires a Facebook Page token rather than
the user token. The adapter resolves it at call time from
/me/accounts?fields=instagram_business_account,access_token, so:
- the authorized user must manage the Page the Instagram account is linked to;
- the Instagram account must be a Business or Creator account (personal accounts cannot publish through the Graph API);
- a system-user token, or an envelope carrying
ig_user_idtogether withpage_access_token, bypasses the discovery call.
5. Troubleshooting
412at start: Vault envelope missing or lacks keys β recheck Β§2 path.state signature mismatch: INTERNAL_API_TOKEN differs between nodes.- Vendor
invalid_grant: refresh token revoked β disconnect and reconnect.