Some Bex APIs accept a user-consented OAuth access token in addition to a
dashboard session. That is different from a workspace machine API key
exchanged with client_credentials — see REST & GraphQL API.
This guide uses the downloadable sample at
/examples/oauth-user-client/
(Node 22+, no npm dependencies). Source pin: Bex 0eb2036e2.
1. Obtain a registered public client
You need a public client (token_endpoint_auth_method: none) whose redirect
URI exactly matches the sample callback (default
http://127.0.0.1:8765/callback).
Hosted discovery may not advertise registration_endpoint. When it does
not, an installation operator must register the client with supported tooling
and give you the client_id. Do not invent a DCR URL or reuse a first-party /
desktop / CLI client ID.
Confirm issuer metadata at
https://oauth.bex.co/.well-known/oauth-authorization-server (or your
installation’s issuer). The protected-resource document at
https://api.bex.co/.well-known/oauth-protected-resource lists the API audience
(https://api.bex.co/mcp on hosted Bex).
2. Download and configure the sample
curl -fsSLO https://bex.co/examples/oauth-user-client-latest.zip
curl -fsSLO https://bex.co/examples/oauth-user-client-latest.zip.sha256
shasum -a 256 -c oauth-user-client-latest.zip.sha256
unzip oauth-user-client-latest.zip
cd oauth-user-client
cp .env.example .envSet at least BEX_OAUTH_CLIENT_ID. Keep BEX_OAUTH_SCOPES least-privileged
(default includes bex.read). Scopes do not elevate workspace role.
3. Authorize and read
set -a && source .env && set +a
node client.mjsOpen the printed URL, sign in, and approve the client. The sample:
- Listens on the registered loopback callback
- Verifies
stateand exchanges the code with PKCE S256 - Calls
GET /v1/serviceswith the access token - Refreshes and revokes tokens when a refresh token is present
Tokens are never printed. Denied consent or a bad state never triggers a
token exchange.
4. Offline check
Without Bex credentials:
BEX_OAUTH_FIXTURE=1 node client.mjsTroubleshooting
| Symptom | Check |
|---|---|
| Consent rejects PKCE | Use code_challenge_method=S256 only |
invalid_grant on exchange | Redirect URI must match registration exactly |
401 on /v1/services | Need bex.read (or write/sensitive) and a visible workspace |
| Admin APIs still 403 | User must be a workspace administrator; scopes ≠ role |
No registration_endpoint | Ask the operator for a registered public client_id |
MCP clients that manage their own browser login are covered in Connect an Agent and MCP server. Webhook administration still requires an administrator user token — Outbound webhooks.