docs: API landing pages overhaul (#45062)

This commit is contained in:
Chris Chinchilla
2026-04-28 14:13:48 +02:00
committed by GitHub
parent d496170c0a
commit a96d3d2b21
22 changed files with 269 additions and 250 deletions
@@ -328,6 +328,7 @@ export const gettingstarted: NavMenuConstant = {
url: '/guides/getting-started',
items: [
{ name: 'Features', url: '/guides/getting-started/features' },
{ name: 'API Keys', url: '/guides/getting-started/api-keys' },
{ name: 'Architecture', url: '/guides/getting-started/architecture' },
{
name: 'Framework Quickstarts',
@@ -1492,9 +1493,7 @@ export const api: NavMenuConstant = {
name: 'Security',
url: '/guides/api',
items: [
{ name: 'How API Keys work', url: '/guides/api/api-keys' },
{ name: 'Securing your API', url: '/guides/api/securing-your-api' },
{ name: 'Data API', url: '/guides/database/data-api' },
{
name: 'Custom Claims & RBAC',
url: '/guides/api/custom-claims-and-role-based-access-control-rbac',
@@ -2485,7 +2484,7 @@ export const security: NavMenuConstant = {
url: '/guides/deployment/shared-responsibility-model' as `/${string}`,
},
{ name: 'Row Level Security', url: '/guides/database/postgres/row-level-security' },
{ name: 'Data API', url: '/guides/database/data-api' },
{ name: 'Securing your API', url: '/guides/api/securing-your-api' },
],
},
],
+1 -1
View File
@@ -4,7 +4,7 @@ Now that you've created some database tables, you are ready to insert data using
To do this, you need to get the Project URL and key from [the project **Connect** dialog](/dashboard/project/\_?showConnect=true&connectTab={{ .tab }}&framework={{ .framework }}).
[Read the API keys docs](/docs/guides/api/api-keys) for a full explanation of all key types and their uses.
[Read the API keys docs](/docs/guides/getting-started/api-keys) for a full explanation of all key types and their uses.
<Admonition type="note" title="Changes to API keys">
@@ -8,7 +8,7 @@ Now that you've created some database tables, you are ready to insert data using
To do this, you need to get the Project URL and key from [the project **Connect** dialog](/dashboard/project/\_?showConnect=true&connectTab={{ .tab }}&framework={{ .framework }}).
[Read the API keys docs](/docs/guides/api/api-keys) for a full explanation of all key types and their uses.
[Read the API keys docs](/docs/guides/getting-started/api-keys) for a full explanation of all key types and their uses.
<Admonition type="note" title="Changes to API keys">
@@ -23,7 +23,7 @@ className="rounded-lg border border-foreground/10 bg-surface-100 text-foreground
3. Authenticate with HTTP Basic Auth:
- **Username**: `service_role`
- **Password**: a **Secret API key** (`sb_secret_...`). You can create/copy it in [**Project Settings → API Keys**](/dashboard/project/_/settings/api-keys). For more context, see [Understanding API keys](/docs/guides/api/api-keys).
- **Password**: a **Secret API key** (`sb_secret_...`). You can create/copy it in [**Project Settings → API Keys**](/dashboard/project/_/settings/api-keys). For more context, see [Understanding API keys](/docs/guides/getting-started/api-keys).
Testing locally is as simple as running `curl` with your Secret API key:
+13 -15
View File
@@ -12,18 +12,25 @@ The API is auto-generated from your database and is designed to get you building
You can use them directly from the browser (two-tier architecture), or as a complement to your own API server (three-tier architecture).
<Admonition type="tip" title="Looking for your Data API URL and Keys?">
- You can find the API URL in the [**Integrations > Data API**](/dashboard/project/_/integrations/data_api/overview) section of the Dashboard.
- You can find the API Keys in the [**Settings > API Keys**](/dashboard/project/_/settings/api-keys/) section of the Dashboard.
</Admonition>
## Features [#rest-api-overview]
Supabase provides a RESTful API using [PostgREST](https://postgrest.org/). This is a very thin API layer on top of Postgres.
Supabase provides a RESTful API using [PostgREST](https://postgrest.org/), a thin API layer on top of Postgres.
It exposes everything you need from a CRUD API at the URL `https://<project_ref>.supabase.co/rest/v1/`.
The REST interface is automatically reflected from your database's schema and is:
- **Instant and auto-generated.** <br />As you update your database the changes are immediately accessible through your API.
- **Self documenting.** <br />Supabase generates documentation in the Dashboard which updates as you make database changes.
- **Secure.** <br />The API is configured to work with Postgres's Row Level Security, provisioned behind an API gateway with key-auth enabled.
- **Fast.** <br />Our benchmarks for basic reads are more than 300% faster than Firebase. The API is a very thin layer on top of Postgres, which does most of the heavy lifting.
- **Scalable.** <br />The API can serve thousands of simultaneous requests, and works well for Serverless workloads.
- **Instant and auto-generated:** As you update your database the changes are immediately accessible through your API.
- **Self documenting:** Supabase generates documentation in the Dashboard which updates as you make database changes.
- **Secure:** The API is configured to work with Postgres's Row Level Security, provisioned behind an API gateway with key-auth enabled.
- **Fast:** Our benchmarks for basic reads are more than 300% faster than Firebase. The API is a very thin layer on top of Postgres, which does most of the heavy lifting.
- **Scalable:** The API can serve thousands of simultaneous requests, and works well for Serverless workloads.
The reflected API is designed to retain as much of Postgres' capability as possible including:
@@ -35,12 +42,3 @@ The reflected API is designed to retain as much of Postgres' capability as possi
- The Postgres security model - including Row Level Security, Roles, and Grants.
The REST API resolves all requests to a single SQL statement leading to fast response times and high throughput.
Reference:
- [Docs](https://postgrest.org/)
- [Source Code](https://github.com/PostgREST/postgrest)
## API URL and keys
You can find the API URL and Keys in the [Dashboard](/dashboard/project/_/settings/api-keys).
@@ -77,7 +77,7 @@ In most cases, you can get the correct key from [the Project's **Connect** dialo
</Admonition>
[Read the API keys docs](/docs/guides/api/api-keys) for a full explanation of all key types and their uses.
[Read the API keys docs](/docs/guides/getting-started/api-keys) for a full explanation of all key types and their uses.
The REST API is accessible through the URL `https://<project_ref>.supabase.co/rest/v1`
+66 -48
View File
@@ -1,22 +1,20 @@
---
title: 'Build an API route in less than 2 minutes.'
subtitle: 'Create your first API route by creating a table called `todos` to store tasks.'
subtitle: 'Create your first API route by creating a public `leaderboard` table.'
breadcrumb: 'API Quickstart'
hideToc: true
---
Let's create our first REST route which we can query using `cURL` or the browser.
We'll create a database table called `todos` for storing tasks. This creates a corresponding API route `/rest/v1/todos` which can accept `GET`, `POST`, `PATCH`, & `DELETE` requests.
This guide covers creating a REST route you can query using `cURL` or the browser by creating a database table called `leaderboard` to hold player scores. This creates a corresponding API route `/rest/v1/leaderboard` which can accept `GET`, `POST`, `PATCH`, and `DELETE` requests.
<StepHikeCompact>
<StepHikeCompact.Step step={1}>
<StepHikeCompact.Details title="Set up a Supabase project with a 'todos' table">
<StepHikeCompact.Details title="Set up a Supabase project with a 'leaderboard' table">
[Create a new project](/dashboard) in the Supabase Dashboard.
[Create a new project](/dashboard/_) in the Supabase Dashboard.
After your project is ready, create a table in your Supabase database. You can do this with either the Table interface or the [SQL Editor](/dashboard/project/_/sql).
After your project is ready, create a table in your Supabase database. You can do this with either the [Table Editor](/dashboard/project/_/editor) or the [SQL Editor](/dashboard/project/_/sql).
</StepHikeCompact.Details>
@@ -32,11 +30,13 @@ We'll create a database table called `todos` for storing tasks. This creates a c
<TabPanel id="sql" label="SQL">
```sql
-- Create a table called "todos"
-- with a column to store tasks.
create table todos (
-- Create a "leaderboard" table to store
-- player names and their scores.
create table leaderboard (
id serial primary key,
task text
player text not null,
score integer not null default 0,
created_at timestamptz default now()
);
```
@@ -44,10 +44,9 @@ We'll create a database table called `todos` for storing tasks. This creates a c
<TabPanel id="dashboard" label="Dashboard">
1. Go to the [**Table editor**](/dashboard/project/_/editor) section in the Dashboard.
2. Click **New Table** and create a table with the name `todos`.
3. Click **Save**.
4. Click **New Column** and create a column with the name `task` and type `text`.
5. Click **Save**.
2. Click **New Table** and create a table with the name `leaderboard`.
3. Add a `player` column of type `text` and a `score` column of type `int4`.
4. Click **Save**.
</TabPanel>
</Tabs>
@@ -59,9 +58,9 @@ We'll create a database table called `todos` for storing tasks. This creates a c
<StepHikeCompact.Step step={2}>
<StepHikeCompact.Details title="Enable Data API access to Anon Role">
Expose the `todos` table through the Data API so it can be queried over HTTP.
Expose the `leaderboard` table through the Data API so it can be queried over HTTP. A leaderboard is meant to be public, so anonymous clients only need read access.
For more control over which tables and functions are exposed, see [Expose specific tables and functions](/docs/guides/database/data-api#expose-specific-tables-and-functions-recommended).
For more control over which tables and functions are exposed, read the [Grant access explicitly guide](/docs/guides/api/securing-your-api#grant-access-explicitly).
</StepHikeCompact.Details>
@@ -78,13 +77,13 @@ We'll create a database table called `todos` for storing tasks. This creates a c
```sql
-- Allow read-only access for anonymous clients
grant select on public.todos to anon;
grant select on public.leaderboard to anon;
```
</TabPanel>
<TabPanel id="dashboard" label="Dashboard">
Go to [**Integrations > Data API > Settings**](/dashboard/project/_/integrations/data_api/settings). Under **Exposed schemas**, make sure `public` is included, then under **Exposed tables**, toggle on access for the `todos` table.
In the [**Integrations > Data API > Settings**](/dashboard/project/_/integrations/data_api/settings) section of the Dashboard. Under **Exposed schemas**, make sure `public` is included, then under **Exposed tables**, toggle on access for the `leaderboard` table.
</TabPanel>
</Tabs>
@@ -97,7 +96,7 @@ We'll create a database table called `todos` for storing tasks. This creates a c
<StepHikeCompact.Details title="Configure RLS">
Turn on Row Level Security for this table and create the policies that control who can read and write rows.
Enable Row Level Security (RLS) for this table and create the policies that control who can read and write rows. For a leaderboard, anyone should be able to read scores. Only authenticated users should be able to submit or update them.
</StepHikeCompact.Details>
@@ -105,20 +104,26 @@ We'll create a database table called `todos` for storing tasks. This creates a c
```sql
-- Turn on RLS
alter table "todos"
alter table "leaderboard"
enable row level security;
-- Allow anonymous access
create policy "Allow public access"
on todos
-- Anyone can read the leaderboard
create policy "Leaderboard is public"
on leaderboard
for select
to anon
to anon, authenticated
using (true);
-- Allow authenticated users to read and modify todos
create policy "Allow authenticated users to manage todos"
on todos
for all
-- Authenticated users can submit and update scores
create policy "Authenticated users can submit scores"
on leaderboard
for insert
to authenticated
with check (true);
create policy "Authenticated users can update scores"
on leaderboard
for update
to authenticated
using (true)
with check (true);
@@ -131,7 +136,7 @@ We'll create a database table called `todos` for storing tasks. This creates a c
<StepHikeCompact.Step step={4}>
<StepHikeCompact.Details title="Enable Data API access for authenticated and service roles">
Now that RLS is in place, grant write access to the `authenticated` and `service_role` roles.
With RLS setup, grant write access to the `authenticated` and `service_role` roles.
</StepHikeCompact.Details>
@@ -139,8 +144,8 @@ We'll create a database table called `todos` for storing tasks. This creates a c
```sql
-- Grant write access only after RLS and policies are in place
grant select, insert, update, delete on public.todos to authenticated;
grant select, insert, update, delete on public.todos to service_role;
grant select, insert, update, delete on public.leaderboard to authenticated;
grant select, insert, update, delete on public.leaderboard to service_role;
```
</StepHikeCompact.Code>
@@ -150,19 +155,19 @@ We'll create a database table called `todos` for storing tasks. This creates a c
<StepHikeCompact.Step step={5}>
<StepHikeCompact.Details title="Insert some dummy data">
Now we can add some data to our table which we can access through our API.
Now add some scores to the table so the API has something to query.
</StepHikeCompact.Details>
<StepHikeCompact.Code>
```sql
insert into todos (task)
insert into leaderboard (player, score)
values
('Create tables'),
('Enable security'),
('Add data'),
('Fetch data from the API');
('alice', 4200),
('bob', 3700),
('carol', 5100),
('dave', 2900);
```
</StepHikeCompact.Code>
@@ -172,7 +177,7 @@ We'll create a database table called `todos` for storing tasks. This creates a c
<StepHikeCompact.Step step={6}>
<StepHikeCompact.Details title="Fetch the data">
Find your API URL and Keys in your Dashboard [API Settings](/dashboard/project/_/settings/api). You can now query your "todos" table by appending `/rest/v1/todos` to the API URL.
You can find your API URL and Keys in the [**Settings > API Settings**](/dashboard/project/_/settings/api) section of the Dashboard. Query the `leaderboard` table by appending `/rest/v1/leaderboard` to the API URL.
Copy this block of code, substitute `<PROJECT_REF>` and `<PUBLISHABLE_KEY>`, then run it from a terminal.
@@ -180,7 +185,7 @@ We'll create a database table called `todos` for storing tasks. This creates a c
<StepHikeCompact.Code>
```bash Terminal
curl 'https://<PROJECT_REF>.supabase.co/rest/v1/todos' \
curl 'https://<PROJECT_REF>.supabase.co/rest/v1/leaderboard?select=*&order=score.desc' \
-H "apikey: <PUBLISHABLE_KEY>"
```
@@ -198,14 +203,13 @@ There are several options for accessing your data:
You can query the route in your browser, by appending the `publishable` key as a query parameter:
`https://<PROJECT_REF>.supabase.co/rest/v1/todos?apikey=<PUBLISHABLE_KEY>`
`https://<PROJECT_REF>.supabase.co/rest/v1/leaderboard?apikey=<PUBLISHABLE_KEY>`
### Curl
```
curl 'https://<PROJECT_REF>.supabase.co/rest/v1/todos?select=*' \
```sh
curl 'https://<PROJECT_REF>.supabase.co/rest/v1/leaderboard?select=*&order=score.desc' \
-H "apikey: <PUBLISHABLE_KEY>" \
-H "Authorization: Bearer <PUBLISHABLE_KEY>"
```
### Client libraries
@@ -222,7 +226,10 @@ We provide a number of [Client Libraries](https://github.com/supabase/supabase#c
<TabPanel id="js" label="JavaScript">
```js
const { data, error } = await supabase.from('todos').select()
const { data, error } = await supabase
.from('leaderboard')
.select()
.order('score', { ascending: false })
```
</TabPanel>
@@ -230,7 +237,10 @@ const { data, error } = await supabase.from('todos').select()
<TabPanel id="dart" label="Dart">
```dart
final data = await supabase.from('todos').select('*');
final data = await supabase
.from('leaderboard')
.select('*')
.order('score', ascending: false);
```
</TabPanel>
@@ -239,7 +249,12 @@ final data = await supabase.from('todos').select('*');
<TabPanel id="python" label="Python">
```python
response = supabase.table('todos').select("*").execute()
response = (
supabase.table('leaderboard')
.select("*")
.order('score', desc=True)
.execute()
)
```
</TabPanel>
@@ -248,7 +263,10 @@ response = supabase.table('todos').select("*").execute()
<TabPanel id="swift" label="Swift">
```swift
let response = try await supabase.from("todos").select()
let response = try await supabase
.from("leaderboard")
.select()
.order("score", ascending: false)
```
</TabPanel>
@@ -1,12 +1,81 @@
---
id: 'securing-your-api'
title: 'Securing your API'
description: 'Securing your Data API with Postgres Row Level Security.'
description: 'Secure your Data API with explicit grants and Postgres Row Level Security.'
---
The data APIs are designed to work with Postgres Row Level Security (RLS). If you use [Supabase Auth](/docs/guides/auth), you can restrict data based on the logged-in user.
The Data API is designed to work with Postgres' built-in access controls. Two layers work together:
To control access to your data, you can use [Policies](/docs/guides/auth#policies).
1. **Grants** determine which Postgres roles (`anon`, `authenticated`, `service_role`) can reach a given table, view, or function over the Data API.
2. **Row Level Security (RLS) policies** then determine which rows those roles can read or modify from the tables exposed in step 1.
3. **Both together** grant control _whether_ a role can touch an object. RLS controls _what_ rows they see.
## Grant access explicitly
A table isn't reachable through the Data API unless you have granted a role privileges on it. Grant the minimum privileges each role needs. For example:
```sql
-- Read-only access for anonymous clients
grant select on table public.your_table to anon;
-- Full access for signed-in users (still subject to RLS)
grant select, insert, update, delete on table public.your_table to authenticated;
-- Full access for server-side code using the service role
grant select, insert, update, delete on table public.your_table to service_role;
-- For functions, grant EXECUTE to the roles that should call them
grant execute on function public.your_function() to anon, authenticated;
```
If a required grant is missing, PostgREST returns a `42501` error with a hint that names the exact `GRANT` statement you need:
```json
{
"code": "42501",
"message": "permission denied for table your_table",
"hint": "Grant the required privileges to the current role with: GRANT SELECT ON public.your_table TO anon;"
}
```
See [the Database API 42501 errors troubleshooting guide](/docs/guides/troubleshooting/database-api-42501-errors) for the full troubleshooting flow.
<Admonition type="tip">
Bundle grants with your RLS setup in the same migration. They belong together: `grant` controls role access, `enable row level security` and policies control row access.
</Admonition>
## Default privileges for new tables and functions
By default on existing projects, tables and functions you create in `public` are automatically granted `SELECT`, `INSERT`, `UPDATE`, `DELETE` (or `EXECUTE` for functions) to `anon`, `authenticated`, and `service_role`. That means a new table is reachable through the Data API the moment it lands, even if you forgot to enable RLS or did not intend to expose it.
Supabase is moving the platform default to **revoke** these automatic grants, so that exposure becomes opt-in:
{/* TODO: link to changelog */}
To opt an existing project in today, open the [SQL Editor](/dashboard/project/_/sql/new) and run:
```sql
alter default privileges for role postgres in schema public
revoke select, insert, update, delete on tables from anon, authenticated, service_role;
alter default privileges for role postgres in schema public
revoke execute on functions from anon, authenticated, service_role;
alter default privileges for role postgres in schema public
revoke usage, select on sequences from anon, authenticated, service_role;
alter default privileges for role postgres in schema public
revoke execute on functions from public;
```
## Disable the Data API
If your app never uses Supabase client libraries, REST, or GraphQL data endpoints, turn the Data API off:
1. Open the [Data API integration overview](/dashboard/project/_/integrations/data_api/overview) in the Dashboard.
2. Turn **Enable Data API** off.
With the Data API disabled, none of the auto-generated REST endpoints respond, regardless of grants or RLS.
## Add RLS policies
@@ -39,7 +108,7 @@ Any table created through the Supabase Dashboard will have RLS enabled by defaul
```sql
alter table
todos enable row level security;
your_table enable row level security;
```
</TabPanel>
@@ -49,7 +118,7 @@ With RLS enabled, you can create Policies that allow or disallow users to access
<Admonition type="danger">
Any exposed table **without RLS enabled** can be accessed by roles with matching Data API grants (for example, `anon`). Always make sure RLS is enabled, or that you've got other controls in place to avoid unauthorized access to your project's data.
Any granted table **without RLS enabled** can be accessed by roles with matching Data API grants (for example, `anon`). Always make sure RLS is enabled, or that you've got other controls in place to avoid unauthorized access to your project's data.
</Admonition>
@@ -255,14 +324,14 @@ To clear old entries in the `private.rate_limits` table, set up a [pg_cron](/doc
<TabPanel id="use-additional-api-key" label="Use additional API keys">
Some applications can benefit from using additional API keys managed by the application **in addition to the [Supabase API keys](/docs/guides/api/api-keys)**. This is commonly necessary in cases like:
Some applications can benefit from using additional API keys managed by the application **in addition to the [Supabase API keys](/docs/guides/getting-started/api-keys)**. This is commonly necessary in cases like:
- Applications that use the Data API without RLS policies.
- Applications that do not use [Supabase Auth](/auth) or any other authentication system and rely on the `anon` role.
<Admonition type="tip">
Using the `apikey` header with the [Supabase API keys](/docs/guides/api/api-keys) is mandatory and not configurable. If you use additional API keys, you have to distribute both the `publishable` API key and your application's custom API key.
Using the `apikey` header with the [Supabase API keys](/docs/guides/getting-started/api-keys) is mandatory and not configurable. If you use additional API keys, you have to distribute both the `publishable` API key and your application's custom API key.
</Admonition>
+2 -2
View File
@@ -67,7 +67,7 @@ A [digital signature](https://en.wikipedia.org/wiki/Digital_signature) using a [
Supabase creates JWTs in these cases for you:
1. When using Supabase Auth, an access token (JWT) is created for each user while they remain signed in. These are short lived, so they are continuously issued as your user interacts with Supabase APIs.
2. As the legacy JWT-based [API keys](/docs/guides/api/api-keys) `anon` and `service_role`. These have a 10 year expiry and are signed with a shared secret, making them hard to rotate or expire. These JWTs express public access via the `anon` key, or elevated access via the `service_role` key. We strongly recommend switching to publishable and secret API keys.
2. As the legacy JWT-based [API keys](/docs/guides/getting-started/api-keys) `anon` and `service_role`. These have a 10 year expiry and are signed with a shared secret, making them hard to rotate or expire. These JWTs express public access via the `anon` key, or elevated access via the `service_role` key. We strongly recommend switching to publishable and secret API keys.
3. On-the-fly when using publishable or secret API keys. Each API key is transformed into a short-lived JWT that is then used to authorize access to your data. Accessing these short-lived tokens is generally not possible.
In addition to creating JWTs, Supabase can also accept JWTs from other Auth servers via the [Third-Party Auth](/docs/guides/auth/third-party/overview) feature or ones you've made yourself using the legacy JWT secret or if you've imported in [JWT Signing Key](/docs/guides/auth/signing-keys).
@@ -265,4 +265,4 @@ Check the JWT verification libraries for your language on how to securely verify
- JWT debugger: https://jwt.io/
- [JWT Signing Keys](/docs/guides/auth/signing-keys)
- [JWT Claims Reference](/docs/guides/auth/jwt-fields) - Complete reference for all JWT claims used by Supabase Auth
- [API keys](/docs/guides/api/api-keys)
- [API keys](/docs/guides/getting-started/api-keys)
@@ -46,7 +46,7 @@ The table below shows the rate limit quotas and additional details for authentic
## IP address forwarding
By default, Supabase Auth uses the IP address of the client for rate limiting. In certain cases, such as when using server-side frameworks or proxies in front of a project, it may be necessary to forward the end-user IP address to avoid being rate limited based on the address of the server-side client. To use a forwarded IP address for rate limiting in Supabase Auth, set the `Sb-Forwarded-For` header to the end-user IP address and make a request with a [secret API key](/docs/guides/api/api-keys). Publishable API keys and legacy `anon`/`service_role` API keys are not supported.
By default, Supabase Auth uses the IP address of the client for rate limiting. In certain cases, such as when using server-side frameworks or proxies in front of a project, it may be necessary to forward the end-user IP address to avoid being rate limited based on the address of the server-side client. To use a forwarded IP address for rate limiting in Supabase Auth, set the `Sb-Forwarded-For` header to the end-user IP address and make a request with a [secret API key](/docs/guides/getting-started/api-keys). Publishable API keys and legacy `anon`/`service_role` API keys are not supported.
IP address forwarding must be explicitly enabled for new projects. You can enable this feature in your project under the **IP Address Forwarding** section of your project's rate limit settings at [**Authentication** > **Rate Limits**](/dashboard/project/_/auth/rate-limits).
+54 -12
View File
@@ -20,17 +20,17 @@ When a JWT is issued by Supabase Auth, the key used to create its [signature](ht
### Benefits of the signing keys system
We've designed the Signing keys system to address many problems the legacy system had. It goes hand-in-hand with the [publishable and secret API keys](/docs/guides/api/api-keys).
We've designed the Signing keys system to address many problems the legacy system had. It goes hand-in-hand with the [publishable and secret API keys](/docs/guides/getting-started/api-keys).
| Benefit | Legacy JWT secret | JWT signing keys |
| ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Performance | Increased app latency as JWT validation is done by Auth server. | If using asymmetric signing key, JWT validation is fast and does not involve Auth server. |
| Reliability | To ensure secure revocation, Auth server is in the hot path of your application. | If using asymmetric signing key, JWT validation is local and fast and does not involve Auth server. |
| Security | Requires changing of your application's backend components to fully revoke a compromised secret. | If using asymmetric signing key, revocation is automatic via the key discovery endpoint. |
| Zero-downtime rotation | Downtime, sometimes being significant. Requires careful coordination with [API keys](/docs/guides/api/api-keys). | No downtime, as each rotation step is independent and reversible. |
| Users signed out during rotation | Currently active users get immediately signed out. | No users get signed out. |
| Independence from API keys | `anon` and `service_role` must be rotated simultaneously. | [Publishable and secret API keys](/docs/guides/api/api-keys) no longer are based on the JWT signing key and can be independently managed. |
| Security compliance frameworks (SOC2, etc.) | Difficult to remain aligned as the secret can be extracted from Supabase. | Easier alignment as the private key or shared secret can't be extracted. [Row Level Security](/docs/guides/database/postgres/row-level-security) has strong key revocation guarantees. |
| Benefit | Legacy JWT secret | JWT signing keys |
| ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Performance | Increased app latency as JWT validation is done by Auth server. | If using asymmetric signing key, JWT validation is fast and does not involve Auth server. |
| Reliability | To ensure secure revocation, Auth server is in the hot path of your application. | If using asymmetric signing key, JWT validation is local and fast and does not involve Auth server. |
| Security | Requires changing of your application's backend components to fully revoke a compromised secret. | If using asymmetric signing key, revocation is automatic via the key discovery endpoint. |
| Zero-downtime rotation | Downtime, sometimes being significant. Requires careful coordination with [API keys](/docs/guides/getting-started/api-keys). | No downtime, as each rotation step is independent and reversible. |
| Users signed out during rotation | Currently active users get immediately signed out. | No users get signed out. |
| Independence from API keys | `anon` and `service_role` must be rotated simultaneously. | [Publishable and secret API keys](/docs/guides/getting-started/api-keys) no longer are based on the JWT signing key and can be independently managed. |
| Security compliance frameworks (SOC2, etc.) | Difficult to remain aligned as the secret can be extracted from Supabase. | Easier alignment as the private key or shared secret can't be extracted. [Row Level Security](/docs/guides/database/postgres/row-level-security) has strong key revocation guarantees. |
## Getting started
@@ -58,7 +58,7 @@ Key rotation and revocation are one of the most important processes for maintain
- The legacy JWT secret has been leaked in logs, committed to source control, or accidentally exposed in the frontend build of your application, a library, desktop or mobile app package, etc.
- You suspect that a [member of your organization](/docs/guides/platform/access-control) has lost control of their devices, and a malicious actor may have accessed the JWT secret via the Supabase dashboard or by accessing your application's backend configuration.
- You suspect that an ex-team-member of your organization may be a malicious actor, by abusing the power the legacy JWT secret provides.
- Make sure you also switch to [publishable and secret API keys](/docs/guides/api/api-keys) and disable the `anon` and `service_role` keys.
- Make sure you also switch to [publishable and secret API keys](/docs/guides/getting-started/api-keys) and disable the `anon` and `service_role` keys.
- If you've imported a private key, and you're suspecting that this private key has been compromised on your end similarly.
**Closer alignment to security best practices and compliance frameworks (SOC2, PCI-DSS, ISO27000, HIPAA, ...)**
@@ -233,7 +233,7 @@ Finally, you can use your newly minted JWT by setting the `Authorization: Bearer
<Admonition type="note">
A separate `apikey` header is required to access your project's APIs. This can be a [publishable, secret or the legacy `anon` or `service_role` keys](/docs/guides/api/api-keys). Using your minted JWT is not possible in this header.
A separate `apikey` header is required to access your project's APIs. This can be a [publishable, secret or the legacy `anon` or `service_role` keys](/docs/guides/getting-started/api-keys). Using your minted JWT is not possible in this header.
</Admonition>
@@ -248,3 +248,45 @@ This is to ensure you have the ability, should you need it, to go back to the le
### Why does revoking the legacy JWT secret require disabling of `anon` and `service_role` API keys?
Unfortunately `anon` and `service_role` are not just API keys, but are also valid JSON Web Tokens, signed by the legacy JWT secret. Revoking the legacy JWT secret means that your application no longer trusts any JWT signed with it. Therefore before you revoke the legacy JWT secret, you must disable the `anon` and `service_role` to ensure a consistent security setup.
### Using JWT-based `anon` key in a mobile, desktop, or CLI application and need to rotate a `service_role` JWT secret?
If the JWT secret is secure, substitute the `service_role` JWT-based key with a new secret key which you can create in the [**Settings > API Keys**](/dashboard/project/_/settings/api-keys/) section of the Dashboard. This prevents downtime for your application.
### Why are `anon` and `service_role` JWT-based keys no longer recommended?
Since the start of Supabase, the JWT-based `anon` and `service_role` keys were the right trade-off against simplicity and relative security for your project. Unfortunately they pose some real challenges in live applications, especially around rotation and security best practices.
The main reasons for preferring the publishable and secret keys (`sb_publishable_...` and `sb_secret_...`) are:
- Tight coupling between the JWT secret (which itself can be compromised, if you mint your own JWTs), the `anon` (low privilege) and `service_role` (high privilege) and `authenticated` (issued by Supabase Auth) Postgres roles.
- Inability to independently rotate each aspect of the keys, without downtime.
- Inability to roll-back an unnecessary or problematic JWT secret rotation.
- Publishing new versions of mobile applications can take days and often weeks in the app review phase with Apple's App Store and Google's Play Store. A forced rotation can cause weeks of downtime for mobile app users.
- Users may continue using desktop, CLI and mobile apps with very old versions, making rotation impossible without a forced version upgrade.
- JWTs had 10-year expiry duration, giving malicious actors more to work with.
- JWTs were self-referential and full of redundant information not necessary for achieving their primary purpose.
- JWTs are large, hard to parse, verify, and manipulate -- leading to insecure logging or bad security practices.
- They were signed with a symmetric JWT secret.
### Can you still use an old `anon` and `service-role` API keys after enabling the publishable and secret keys?
Yes. This allows you to transition between the API keys with zero downtime by gradually swapping your clients while both sets of keys are active. See the next question for how to deactivate your keys once all your clients are switched over.
### How to deactivate the `anon` and `service_role` JWT-based API keys after moving to publishable and secret keys?
You can do this in the [**Settings > API Keys**](/dashboard/project/_/settings/api-keys/) section of the Dashboard. To prevent downtime in your application's components, use the last used indicators on the page to confirm that these are no longer used before deactivating.
You can re-activate them should you need to.
### How are publishable and secret keys implemented on the hosted platform?
When your applications use the Supabase APIs they go through a component called the API Gateway on the Supabase hosted platform. This provides us (and therefore you) with the following features:
- Observability and logging.
- Performance and request routing (such as to read-replicas).
- Security, for blocking malicious patterns or behavior on a global scale.
This API Gateway component is able to verify the API key (sent in the `apikey` request header, or for WebSocket in a query param) against your project's publishable and secret key list. If the match is found, it mints a temporary, short-lived JWT that is then forwarded down to your project's servers.
It may be possible to replicate similar behavior if you self-host by using programmable proxies such as [Kong](https://konghq.com/), [Envoy](https://www.envoyproxy.io/), [NGINX](https://nginx.org/) or similar.
@@ -1,47 +0,0 @@
---
title: 'Data API'
description: 'Quick options for managing Data API exposure and access.'
---
The Supabase Data API is a standalone server that sits between your application client code and your database. It automatically generates a fully RESTful API based on your database structure, allowing you to interact with your database through HTTP endpoints.
With the Data API, you have granular control over exposure: expose specific tables and functions by granting Data API roles the access they need, or enable **Default privileges for new entities** to automatically grant access to new tables and functions in `public`.
<Admonition type="caution">
Any table that is exposed through the Data API should have [Row Level Security (RLS) enabled](/docs/guides/database/postgres/row-level-security) to prevent unauthorized data access.
</Admonition>
## Expose specific tables and functions (recommended)
In [Data API integrations settings](/dashboard/project/_/integrations/data_api/settings), expose specific tables and functions and grant only the privileges each role needs.
```sql
grant select on table public.your_table to anon;
grant select, insert, update, delete on table public.your_table to authenticated;
grant execute on function public.your_function to anon, authenticated;
```
## Use default privileges for new entities in `public`
If you want new entities in `public` to be accessible automatically, enable **Default privileges for new entities** in the [**Integrations > Data API**](/dashboard/project/_/integrations/data_api/settings) section of the Dashboard. This applies only to new tables and functions in `public`.
```sql
alter default privileges for role postgres in schema public
grant select, insert, update, delete on tables to anon, authenticated, service_role;
alter default privileges for role postgres in schema public
grant execute on functions to anon, authenticated, service_role;
```
## Disable the Data API completely
If your app never uses Supabase client libraries, REST, or GraphQL data endpoints:
1. In the [**Integrations > Data API**](/dashboard/project/_/integrations/data_api/overview) section of the Dashboard.
1. Turn **Enable Data API** off.
## Learn more
To learn more about the Data API, see the [full guide](/docs/guides/api).
@@ -19,7 +19,7 @@ Put custom server-side logic between your client and database with [Edge Functio
### Direct database connections
Connect to Postgres with a connection string from trusted servers, workers, or tools. Keep database credentials secret and use the right [connection method](/docs/guides/database/connecting-to-postgres) for your environment. You can [disable the Data API](/docs/guides/database/data-api#disable-the-data-api-completely) if your app only uses direct connections.
Connect to Postgres with a connection string from trusted servers, workers, or tools. Keep database credentials secret and use the right [connection method](/docs/guides/database/connecting-to-postgres) for your environment. You can [disable the Data API](/docs/guides/api/securing-your-api#disable-the-data-api) if your app only uses direct connections.
## Frontend access
@@ -44,6 +44,6 @@ Supabase and Postgres provide you with multiple ways to manage security, includi
- [Row Level Security](/docs/guides/database/postgres/row-level-security)
- [Column Level Security](/docs/guides/database/postgres/column-level-security)
- [Data API](/docs/guides/database/data-api)
- [Securing your API](/docs/guides/api/securing-your-api)
- [Managing Postgres roles](/docs/guides/database/postgres/roles)
- [Managing secrets with Vault](/docs/guides/database/vault)
@@ -6,6 +6,12 @@ description: "First-layer protection for your project's data"
Supabase gives you fine-grained control over which application components are allowed to access your project through API keys.
<Admonition type="tip" title="Looking for your API Keys?">
In most cases, you can get the correct key from [the Project's **Connect** dialog](/dashboard/project/_?showConnect=true), but if you want a specific key, you can find all keys in the [**Settings > API Keys**](/dashboard/project/_/settings/api-keys/) section of the Dashboard:
</Admonition>
API keys provide the first layer of authentication for data access. Auth then builds upon that. This chart covers the differences:
| Responsibility | Question | Answer |
@@ -17,77 +23,55 @@ API keys provide the first layer of authentication for data access. Auth then bu
An API key authenticates an application component to give it access to Supabase services. An application component might be a web page, a mobile app, or a server. The API key _does not_ distinguish between users, only between applications.
There are 4 types of API keys that can be used with Supabase:
There are 4 types of API keys that you can use with Supabase:
| Type | Format | Privileges | Availability | Use |
| ---------------------------------------------------------- | ---------------------------------------------------------------- | ---------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Publishable&nbsp;key | <span className="!whitespace-nowrap">`sb_publishable_...`</span> | Low | Platform | Safe to expose online: web page, mobile or desktop app, GitHub actions, CLIs, source code. |
| Secret&nbsp;keys | <span className="!whitespace-nowrap">`sb_secret_...`</span> | Elevated | Platform | **Only use in backend components of your app:** servers, already secured APIs (admin panels), [Edge Functions](/docs/guides/functions), microservices, etc. They provide _full access_ to your project's data, bypassing [Row Level Security](/docs/guides/database/postgres/row-level-security). |
| <span className="!whitespace-nowrap">`anon`</span> | JWT (long lived) | Low | <span className="!whitespace-nowrap">Platform, CLI</span> | Exactly like the publishable key. |
| <span className="!whitespace-nowrap">`service_role`</span> | JWT (long lived) | Elevated | <span className="!whitespace-nowrap">Platform, CLI</span> | Exactly like secret keys. |
| <span className="!whitespace-nowrap">`anon`</span> | JWT (long lived) | Low | <span className="!whitespace-nowrap">Platform, CLI</span> | Legacy version of publishable keys. |
| <span className="!whitespace-nowrap">`service_role`</span> | JWT (long lived) | Elevated | <span className="!whitespace-nowrap">Platform, CLI</span> | Legacy version of secret keys. |
<Admonition type="note">
<Admonition type="caution" title="Changes to API keys">
`anon` and `service_role` keys are based on the project's JWT secret. They are generated when your project is created and can only be changed when you rotate the JWT secret. This can cause significant issues in production applications. Use the publishable and secret keys instead.
Supabase has changed the way keys work to improve project security and developer experience. You can read [the full announcement](https://github.com/orgs/supabase/discussions/29260).
`anon` and `service_role` keys are based on the project's JWT secret. They are generated when your project is created and you can only change them when you rotate the JWT secret. This can cause significant issues in production applications. **You should now use the `sb_publishable_xxx` and `sb_secret_xxx` keys instead**.
You can still find legacy keys in the **Legacy anon, service_role API keys** tab of the [**Settings > API Keys**](/dashboard/project/_/settings/api-keys/) section of the Dashboard:
</Admonition>
<Admonition type="note" title="Changes to API keys">
## Publishable keys
Supabase is changing the way keys work to improve project security and developer experience. You can [read the full announcement](https://github.com/orgs/supabase/discussions/29260), but in the transition period, you can use both the current `anon` and `service_role` keys and the new publishable key with the form `sb_publishable_xxx` which will replace the older keys.
</Admonition>
## Where to find keys
You can find API keys in a couple of different places.
In most cases, you can get the correct key from [the Project's **Connect** dialog](/dashboard/project/_?showConnect=true), but if you want a specific key, you can find all keys in [the API Keys section of a Project's Settings page](/dashboard/project/_/settings/api-keys/):
- **For legacy keys**, copy the `anon` key for client-side operations and the `service_role` key for server-side operations from the **Legacy API Keys** tab.
- **For new keys**, open the **API Keys** tab, if you don't have a publishable key already, click **Create new API Keys**, and copy the value from the **Publishable key** section.
## `anon` and publishable keys
The `anon` and publishable keys secure the public components of your application. Public components run in environments where it is impossible to secure any secrets. These include:
Publishable keys identify the public components of your application. Public components run in environments where it is impossible to secure any secrets. These include:
- Web pages, where the key is bundled in source code.
- Mobile or desktop applications, where the key is bundled inside the compiled packages or executables.
- CLI, scripts, tools, or other pre-built executables.
- Other publicly available APIs that return the key without prior additional authorization.
These environments are always considered public because anyone can retrieve the key from the source code or build artifacts. Obfuscation can increase the difficulty, but never eliminate the possibility. (In general, obfuscation, Turing test challenges, and specialized knowledge do not count as authorization for the purpose of securing secrets.)
These environments are always considered public because anyone can retrieve the key from the source code or build artifacts.
### Interaction with Supabase Auth
Using the `anon` or publishable key does not mean that your user is anonymous. (Thinking of both these keys as publishable rather than `anon` makes the mental model clearer.)
Your application can be authenticated with the publishable key, while your user is authenticated (via Supabase Auth) with their personal JWT:
Using a publishable key does not mean that your user is anonymous. You can authenticate your application with the publishable key, while your user is authenticated (via Supabase Auth) with their personal JWT:
| Key | User logged in via Supabase Auth | Postgres role used for RLS, etc. |
| --------------- | -------------------------------- | -------------------------------- |
| Publishable key | No | `anon` |
| `anon` | No | `anon` |
| Publishable key | Yes | `authenticated` |
| `anon` | Yes | `authenticated` |
### Protection
These keys provide first-layer protection to your project's data, performance and bill, such as:
- Providing basic Denial-of-Service protection, by requiring a minimal threshold of knowledge.
- Protecting your bill by ignoring bots, scrapers, automated vulnerability scanners and other well meaning or random Internet activity.
### Security considerations
The publishable and `anon` keys are not intended to protect from the following, since key retrieval is always possible from a public component:
Publishable keys are not intended to protect from the following, since key retrieval is always possible from a public component:
- Static or dynamic code analysis and reverse engineering attempts.
- Use of the Network inspector in the browser.
- Cross-site request forgery, cross-site scripting, phishing attacks.
- Man-in-the-middle attacks.
When using the publishable or `anon` key, access to your project's data is guarded by Postgres via the built-in `anon` and `authenticated` roles. For full protection make sure:
When using a publishable key, access to your project's data is guarded by Postgres via the built-in `anon` and `authenticated` roles. For full protection make sure:
- You have enabled Row Level Security on all tables.
- You regularly review your Row Level Security policies for permissions granted to the `anon` and `authenticated` roles.
@@ -95,9 +79,9 @@ When using the publishable or `anon` key, access to your project's data is guard
Your project's [Security Advisor](/dashboard/project/_/advisors/security) constantly checks for common security problems with the built-in Postgres roles. Make sure you carefully review each finding before dismissing it.
## `service_role` and secret keys
## What secret keys allow access to
Unlike the `anon` and publishable key, the `service_role` and secret keys allow elevated access to your project's data. It is meant to be used only in secure, developer-controlled components of your application, such as:
Unlike publishable keys, secret keys allow elevated access to your project's data. It is meant to be used only in secure, developer-controlled components of your application, such as:
- Servers that implement prior authorization themselves, such as Edge Functions, microservices, traditional or specialized web servers.
- Periodic jobs, queue processors, topic subscribers.
@@ -106,11 +90,11 @@ Unlike the `anon` and publishable key, the `service_role` and secret keys allow
<Admonition type="caution">
Never expose your `service_role` and secret keys publicly. Your data is at risk. **Do not:**
Never expose your secret keys publicly. Your data is at risk. **Do not:**
- Add in web pages, public documents, source code, bundle in executables or packages for mobile, desktop or CLI apps.
- Add it to web pages, public documents, source code, bundle in executables or packages for mobile, desktop or CLI apps.
- Send over chat applications, email or SMS to your peers.
- Never use in a browser, even on `localhost`!
- Never use in a browser, even on `localhost`.
- Do not pass in URLs or query params, as these are often logged.
- Be careful passing them in request headers without prior log sanitization.
- Take extra care logging even potentially **invalid API keys**. Simple typos might reveal the real key in the future.
@@ -120,7 +104,7 @@ Ensure you handle them with care and using [secure coding practices](https://owa
</Admonition>
Secret keys and the `service_role` JWT-based API key authorize access to your project's data via the built-in `service_role` Postgres role. By design, this role has full access to your project's data. It also uses the [`BYPASSRLS` attribute](https://www.postgresql.org/docs/current/ddl-rowsecurity.html#:~:text=BYPASSRLS), skipping any and all Row Level Security policies you attach.
Secret keys authorize access to your project's data via the built-in `service_role` Postgres role. By design, this role has full access to your project's data. It also uses the [`BYPASSRLS` attribute](https://www.postgresql.org/docs/current/ddl-rowsecurity.html#:~:text=BYPASSRLS), skipping any and all Row Level Security policies you attach.
The secret key is an improvement over the old JWT-based `service_role` key, and we recommend using it where possible. It adds more checks to prevent misuse, specifically:
@@ -132,7 +116,7 @@ The secret key is an improvement over the old JWT-based `service_role` key, and
Below are some starting guidelines on how to securely work with secret keys:
- Always work with secret keys on computers you fully own or control.
- Use secure & encrypted send tools to share API keys with others (often provided by good password managers), but prefer the [API Keys](/dashboard/project/_/settings/api-keys) dashboard instead.
- Use secure & encrypted send tools to share API keys with others (often provided by good password managers), but prefer the [**Settings > API Keys**](/dashboard/project/_/settings/api-keys/) section of the Dashboard instead.
- Prefer encrypting them when stored in files or environment variables.
- Do not add in source control, especially for CI scripts and tools. Prefer using the tool's native secrets capability instead.
- Prefer using a separate secret key for each separate backend component of your application, so that if one is found to be vulnerable or to have leaked the key you will only need to change it and not all.
@@ -144,7 +128,7 @@ Below are some starting guidelines on how to securely work with secret keys:
Don't rush if this has happened, or you are suspecting it has. Make sure you have fully considered the situation and have remediated the root cause of the suspicion or vulnerability **first**. Consider using the [OWASP Risk Rating Methodology](https://owasp.org/www-community/OWASP_Risk_Rating_Methodology) as an easy way to identify the severity of the incident and to plan your next steps.
Rotating a secret key (`sb_secret_...`) is easy and painless. Use the [API Keys](/dashboard/project/_/settings/api-keys) dashboard to create a new secret API key, then replace it with the compromised key. Once all components are using the new key, delete the compromised one.
To rotate a secret key (`sb_secret_...`), use the [**Settings > API Keys**](/dashboard/project/_/settings/api-keys/) section of the Dashboard to create a new secret API key, then replace it with the compromised key. Once all components are using the new key, delete the compromised one.
**Deleting a secret key is irreversible and once done it will be gone forever.**
@@ -157,57 +141,3 @@ As the publishable and secret keys are no longer JWT-based, there are some known
- You cannot send a publishable or secret key in the `Authorization: Bearer ...` header, except if the value exactly equals the `apikey` header. In this case, your request will be forwarded down to your project's database, but will be rejected as the value is not a JWT.
- Edge Functions **only support JWT verification** via the `anon` and `service_role` JWT-based API keys. You will need to use the `--no-verify-jwt` option when using publishable and secret keys. The Supabase platform does not verify the `apikey` header when using Edge Functions in this way. Implement your own `apikey`-header authorization logic inside the Edge Function code itself.
- Public Realtime connections are limited to 24 hours in duration, unless the connection is upgraded and further maintained with user-level authentication via Supabase Auth or a supported Third-Party Auth provider.
## Frequently asked questions
{/* supa-mdx-lint-disable Rule004ExcludeWords */}
### I am using JWT-based `anon` key in a mobile, desktop, or CLI application and need to rotate my `service_role` JWT secret?
If the JWT secret is secure, substitute the `service_role` JWT-based key with a new secret key which you can create in the [API Keys](/dashboard/project/_/settings/api-keys) dashboard. This will prevent downtime for your application.
### Can I still use my old `anon` and `service-role` API keys after enabling the publishable and secret keys?
Yes. This allows you to transition between the API keys with zero downtime by gradually swapping your clients while both sets of keys are active. See the next question for how to deactivate your keys once all your clients are switched over.
### How do I deactivate the `anon` and `service_role` JWT-based API keys after moving to publishable and secret keys?
You can do this in the [API Keys](/dashboard/project/_/settings/api-keys) dashboard. To prevent downtime in your application's components, use the last used indicators on the page to confirm that these are no longer used before deactivating.
You can re-activate them should you need to.
### Why are `anon` and `service_role` JWT-based keys no longer recommended?
Since the start of Supabase, the JWT-based `anon` and `service_role` keys were the right trade-off against simplicity and relative security for your project. Unfortunately they pose some real challenges in live applications, especially around rotation and security best practices.
The main reasons for preferring the publishable and secret keys (`sb_publishable_...` and `sb_secret_...`) are:
- Tight coupling between the JWT secret (which itself can be compromised, if you mint your own JWTs), the `anon` (low privilege) and `service_role` (high privilege) and `authenticated` (issued by Supabase Auth) Postgres roles.
- Inability to independently rotate each aspect of the keys, without downtime.
- Inability to roll-back an unnecessary or problematic JWT secret rotation.
- Publishing new versions of mobile applications can take days and often weeks in the app review phase with Apple's App Store and Google's Play Store. A forced rotation can cause weeks of downtime for mobile app users.
- Users may continue using desktop, CLI and mobile apps with very old versions, making rotation impossible without a forced version upgrade.
- JWTs had 10-year expiry duration, giving malicious actors more to work with.
- JWTs were self-referential and full of redundant information not necessary for achieving their primary purpose.
- JWTs are large, hard to parse, verify, and manipulate -- leading to insecure logging or bad security practices.
- They were signed with a symmetric JWT secret.
### Why is there no publishable or secret keys in the CLI / self-hosting?
Publishable and secret keys are only available on the Supabase hosted platform. They are managed by our API Gateway component, which does not currently have a CLI equivalent.
We are looking into providing similar but limited in scope support for publishable or secret keys in the future. For now you can only use the `anon` and `service_role` JWT-based keys there.
For advanced users, see the following question on how these keys are implemented on the hosted platform for an idea on how to provide similar functionality for yourself.
### How are publishable and secret keys implemented on the hosted platform?
When your applications use the Supabase APIs they go through a component called the API Gateway on the Supabase hosted platform. This provides us (and therefore you) with the following features:
- Observability and logging.
- Performance and request routing (such as to read-replicas).
- Security, for blocking malicious patterns or behavior on a global scale.
This API Gateway component is able to verify the API key (sent in the `apikey` request header, or for WebSocket in a query param) against your project's publishable and secret key list. If the match is found, it mints a temporary, short-lived JWT that is then forwarded down to your project's servers.
It may be possible to replicate similar behavior if you self-host by using programmable proxies such as [Kong](https://konghq.com/), [Envoy](https://www.envoyproxy.io/), [NGINX](https://nginx.org/) or similar.
@@ -19,8 +19,7 @@ Various products at Supabase have their own hardening and configuration guides,
- [Row Level Security](/docs/guides/database/postgres/row-level-security)
- [Column Level Security](/docs/guides/database/postgres/column-level-security)
- [Data API](/docs/guides/database/data-api)
- [Additional security controls for the Data API](/docs/guides/api/securing-your-api)
- [Securing your API](/docs/guides/api/securing-your-api)
- [Custom claims and role based access control](/docs/guides/api/custom-claims-and-role-based-access-control-rbac)
- [Managing Postgres roles](/docs/guides/database/postgres/roles)
- [Managing secrets with Vault](/docs/guides/database/vault)
@@ -4,7 +4,7 @@ description: 'Configure new API keys and ES256 asymmetric authentication for sel
subtitle: 'Configure new API keys and ES256 asymmetric authentication for self-hosted Supabase.'
---
You can configure self-hosted Supabase to use the [new API keys](/docs/guides/api/api-keys) alongside the legacy API keys (`ANON_KEY` and `SERVICE_ROLE_KEY` HS256-signed JWTs).
You can configure self-hosted Supabase to use the [new API keys](/docs/guides/getting-started/api-keys) alongside the legacy API keys (`ANON_KEY` and `SERVICE_ROLE_KEY` HS256-signed JWTs).
## Before you begin
@@ -71,7 +71,7 @@ docker compose down && docker compose up -d
### New API keys format
The new API keys use the [same format](/docs/guides/api/api-keys) as the Supabase platform:
The new API keys use the [same format](/docs/guides/getting-started/api-keys) as the Supabase platform:
```
sb_publishable_<22-char-random>_<8-char-checksum>
@@ -267,7 +267,7 @@ end
## Additional resources
- [Understanding API keys](/docs/guides/api/api-keys) - How API keys work on the Supabase platform
- [Understanding API keys](/docs/guides/getting-started/api-keys) - How API keys work on the Supabase platform
- [Auth architecture](/docs/guides/auth/architecture) - How the Auth service handles authentication and token signing
- [JWT Signing Keys](/docs/guides/auth/signing-keys) - Best practices on managing keys used by Supabase Auth to create and verify JSON Web Tokens
- [JSON Web Token (JWT)](/docs/guides/auth/jwts) - How to best use JSON Web Tokens with Supabase
@@ -75,7 +75,7 @@ grant select, insert, update, delete on table public.your_table to anon, authent
Granting privileges allows access to your table through the Data API, so you should ensure you [enable RLS](/docs/guides/database/postgres/row-level-security) and write appropriate policies to protect your data.
For more information, see [Data API](/docs/guides/database/data-api).
For more information, see [Securing your API](/docs/guides/api/securing-your-api).
</Admonition>
@@ -9,7 +9,7 @@ database_id = "caa72a34-696c-47c6-8976-e50cf7fb396e"
<Admonition type="deprecation">
This troubleshooting guide is about rotating **Legacy anon, service_role API keys**. We are deprecating Legacy, and recommend migrating to New API keys. To learn more about API keys, refer to [the API documentation](/docs/guides/api/api-keys).
This troubleshooting guide is about rotating **Legacy anon, service_role API keys**. We are deprecating Legacy, and recommend migrating to New API keys. To learn more about API keys, refer to [the API documentation](/docs/guides/getting-started/api-keys).
</Admonition>
@@ -42,5 +42,5 @@ If you have migrated to new symmetric JWT signing keys:
## Further readings
- [What to do if a secret key or service_role has been leaked or compromised?](/docs/guides/api/api-keys#what-to-do-if-a-secret-key-or-servicerole-has-been-leaked-or-compromised)
- [What to do if a secret key or service_role has been leaked or compromised?](/docs/guides/getting-started/api-keys#what-to-do-if-a-secret-key-or-servicerole-has-been-leaked-or-compromised)
- [JWT Signing Keys](/docs/guides/auth/signing-keys)
@@ -10,7 +10,7 @@ database_id = "677f0a69-e454-4718-ad92-91053d40c085"
<Admonition type="deprecation">
This troubleshooting guide is about rotating **Legacy anon, service_role API keys**. We are deprecating the Legacy API keys, and recommend migrating to New API keys. To learn more about API
keys, refer to [the API documentation](/docs/guides/api/api-keys).
keys, refer to [the API documentation](/docs/guides/getting-started/api-keys).
</Admonition>
@@ -17,7 +17,7 @@ launchweek: '15'
Today we're announcing some long awaited changes in Supabase:
- Support for [asymmetric JWTs with Supabase Auth](/docs/guides/auth/signing-keys).
- [New API keys](/docs/guides/api/api-keys) to help you transition to asymmetric JWTs and improve the security of your apps.
- [New API keys](/docs/guides/getting-started/api-keys) to help you transition to asymmetric JWTs and improve the security of your apps.
<div className="video-container mb-8">
<iframe
+10
View File
@@ -9,6 +9,11 @@ module.exports = [
source: '/auth/Auth',
destination: '/auth',
},
{
permanent: true,
source: '/docs/guides/api/api-keys',
destination: '/docs/guides/getting-started/api-keys',
},
{
permanent: true,
source: '/docs/guides/database/hardening-data-api',
@@ -19,6 +24,11 @@ module.exports = [
source: '/docs/guides/api/hardening-data-api',
destination: '/docs/guides/api/securing-your-api',
},
{
permanent: true,
source: '/docs/guides/database/data-api',
destination: '/docs/guides/api/securing-your-api',
},
{
permanent: true,
source: '/docs/guides/database/postgres/custom-claims-and-role-based-access-control-rbac',
+1
View File
@@ -256,6 +256,7 @@ allow_list = [
"Kysely",
"LangChain",
"Laravel",
"[Ll]eaderboard",
"LineString",
"LinkedIn",
"LlamaIndex",