# Connect Supabase

An account of Supabase is connected once, on the instance, by a person who then gives missions access to its resources; the agent never receives the credential. Postgres, storage, auth and edge functions of Supabase projects, through the Management API.

One account is your company's Supabase OAuth app authorised on an organisation, or a personal access token; one resource is one project (database, storage, auth and edge functions). Supabase runs one project per environment, so the owner of the account labels each project (staging, prod, …) and the permissions tied to an environment apply to the projects carrying that label.

Permissions, presets and tools of this service: [Supabase plugin](/plugins/supabase).

## How to connect

On the instance: Accounts → Connect an account, then pick the service. A company app, when the service needs one, is registered once by an administrator under Settings → Administration → Company apps, or set in the configuration (`providers.<id>.*`, see [configuration keys](/docs/configuration/keys)). Every instance registers its own app: this gateway never uses an app shared with another one.

### The usual way: through your company's OAuth app at the service (one click once the app is registered)

Scopes asked: `all`.

### Another way: with a personal access token pasted by hand

1. Sign in to Supabase as the account the agents will act as.
2. Open Account preferences, Access tokens, then generate a new token.
3. Make it a scoped token: pick the organisation and only the projects the missions need.
4. Grant the permissions below, choose an expiry, and generate the token.
5. Copy the token and paste it here. Supabase shows it once.

Where: [https://supabase.com/dashboard/account/tokens](https://supabase.com/dashboard/account/tokens)

Permissions to grant at the service, and no more:

- Project Settings: read
- API Keys: read
- API Key Secrets: read
- Database: read
- Migrations: read-write
- Advisors: read
- Storage Config: read
- Storage Config: read-write
- Auth Config: read
- Auth Config: read-write
- Edge Functions: read
- Edge Functions: read-write
- Secrets: read
- Secrets: read-write

Recommended expiry: 90 days.

What the connect page asks:

- Personal access token (secret): Prefer a scoped token: it reaches only the projects and permissions you chose.

The service's documentation: [https://supabase.com/docs/guides/platform/personal-access-tokens](https://supabase.com/docs/guides/platform/personal-access-tokens)

## Disconnecting

Revoke your company's OAuth app in the settings of the Supabase organisation, under the authorised OAuth apps.

## Registration notes from the plugin

From the plugin's [README](https://github.com/vaubaan/gateway/blob/main/plugins/supabase/README.md), written for the people who register the app or create the token.

### Credential — the company's Supabase OAuth app

`credential.kind: 'oauth2'`, `refreshable: true` :

| Field              | Value                                                |
| ------------------ | ---------------------------------------------------- |
| `authorizationUrl` | `https://api.supabase.com/v1/oauth/authorize`        |
| `tokenUrl`         | `https://api.supabase.com/v1/oauth/token`            |
| `scopes`           | `['all']` (the app's scopes are set at registration) |
| `pkce`             | `true` (S256)                                        |
| `clientAuthMethod` | `client_secret_basic`                                |

#### Registering the app (once per company)

1. In the Supabase dashboard, open your organization → **OAuth Apps**
   (`https://supabase.com/dashboard/org/<slug>/apps`) and create an app.
2. Set the redirect URL to the callback the instance shows in
   Settings → Administration → Company apps (it is derived from the
   instance `public_url`).
3. Pick the scopes the company is ready to grant the gateway. The plugin
   needs `database:read` for the read-only tools, `database:write` for
   migrations, `secrets:read` for the data-plane tools (it reads the
   project `service_role` key through the Management API), and the
   `auth`, `storage`, `edge_functions`, `environment`, `organizations` and
   `projects` scopes for the corresponding tools and for discovery.
4. Enter the **client id** and **client secret** in the instance
   configuration (Settings → Administration → Company apps). The host uses them for the
   authorization-code flow and for refresh ; the plugin reads neither, and
   nothing from the environment.

Connecting is then one click : the host runs the authorization-code flow
from the spec above and stores the token pair encrypted. Access tokens live
one hour ; the host refreshes them with the standard `refresh_token` grant
and HTTP Basic client authentication (the refresh token rotates), and owns
the refresh timing. A 401/403 upstream throws `UpstreamAuthError`, which
also triggers a refresh in the host.

#### Resource discovery

`discoverResources` lists `GET /v1/organizations` and `GET /v1/projects` and
returns one `Resource` per project : `ref` = project ref, `displayName` =
`<organization> / <project>`, `metadata` = organization, region, status.
The Management API returns the whole list (no paging) ; the plugin caps it
at `MAX_DISCOVERED_PROJECTS` (200) and warns through the logger. The owner
labels each project's `env` on the account's page (Accounts).

### Credential, the other way: a personal access token

Without a company OAuth app — or beside it — an account is connected with a
**personal access token** pasted by hand (`supabaseTokenCredential`,
`src/token.ts`). Create it at https://supabase.com/dashboard/account/tokens,
as the account the agents will act as (a shared service account is fine),
**scoped** to the organisation and projects the missions need, with the
permissions the connect page lists (`guide.permissions`) and an expiry. Every
tool runs with it. The gateway checks it with `GET /v1/organizations` and
seals it; Supabase exposes no expiry and no deletion endpoint for these
tokens, so removing the account tells the person to delete it under Account
preferences → Access tokens. ADR
[`token-connections-beside-the-integration-app`](https://github.com/vaubaan/gateway/blob/main/docs/decisions/token-connections-beside-the-integration-app.md).
