You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 2d666bd
Browse filesBrowse the repository at this point in the historyBrowse files
docs(mcp): scope the Supabase token gate and name the password hook
The MCP reference said that Supabase refuses a connected app's token, with no limit. The gate covers only the Data API, Storage and Realtime. The Supabase Auth API has no client_id check. The reference now names those three surfaces. It also points to the password sign-in hook, which refuses every password sign-in.
The local config.toml now sets secure_password_change = true. A running local stack takes it after a Supabase stop and start. The password hook stays commented out locally, because the e2e scripts and document-swarm sign in with a password.
Refs #441
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: docs/mcp/reference.md
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -23,7 +23,8 @@ Replace `<PUBLIC_RESTAPI_URL>` with your server's value of [`PUBLIC_RESTAPI_URL`
23
23
- Send the token as `Authorization: Bearer <token>`. Replace `<token>` with the access token the host gets at the end of the OAuth flow. The `token` header that other REST routes read is ignored here.
24
24
- Only a token that carries a `client_id` claim is accepted. An OAuth grant adds that claim. A docs.plus browser session token never has it, so it gets `401`.
25
25
- On the docs.plus server, only `/api/mcp` accepts a token with `client_id`. [Authentication](../api/authentication.md#what-each-credential-can-call) says what the other routes do with it.
26
-
- The docs.plus Supabase project refuses a token with `client_id` too. The Data API (tables, RPC and GraphQL) answers `403` with the code `connected_app`. Storage shows the token no objects and refuses its uploads. Realtime refuses it on private channels, and applies the same refusal to database-change subscriptions. So build on the tools below, not on the Supabase APIs. A self-hosted server needs [one Supabase script](../self-hosting/configuration.md#turn-on-the-mcp-connector) for this.
26
+
- The docs.plus Supabase project refuses a token with `client_id` on the Data API, Storage and Realtime. The Data API (tables, RPC and GraphQL) answers `403` with the code `connected_app`. Storage shows the token no objects and refuses its uploads. Realtime refuses it on private channels, and applies the same refusal to database-change subscriptions. So build on the tools below, not on the Supabase APIs. A self-hosted server needs [one Supabase script](../self-hosting/configuration.md#turn-on-the-mcp-connector) for this.
27
+
- The Supabase Auth API has no `client_id` check. The [password sign-in hook](../self-hosting/configuration.md#turn-off-password-sign-in) refuses every password sign-in, so a password that a connected app sets cannot open a session. A self-hosted server must turn that hook on too.
27
28
28
29
**Audience binding is not possible today.** Supabase always sets `aud` to `authenticated`. It never writes the RFC 8707 `resource` into the token ([supabase/auth#2610](https://github.com/supabase/auth/issues/2610)). So `/api/mcp` cannot prove that a token was issued for it. The `client_id` rule is the strongest check Supabase allows.
Copy file name to clipboardExpand all lines: docs/self-hosting/configuration.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -235,6 +235,8 @@ The function is a Custom Access Token hook, which every Supabase plan has. It re
235
235
236
236
**Hosted Supabase.** In the Supabase dashboard, open **Authentication > Hooks**. Add the **Customize Access Token (JWT) Claims** hook, choose **Postgres**, and pick that function. The hook runs each time Supabase issues a token. If sign-in or a token refresh fails after you turn it on, turn the hook off again.
237
237
238
+
**Secure password change.** In the same dashboard, open the **Email** provider settings and turn on **Secure password change**. It asks for a recent sign-in before a password change. Supabase counts a session under 24 hours old as recent, so this setting is only an extra layer. The hook is the control that refuses a password sign-in.
239
+
238
240
**Local stack.**`packages/supabase/config.toml` has the hook block, commented out.
0 commit comments