Understanding API keys | Supabase Docs (original) (raw)


Supabase gives you fine-grained control over which application components are allowed to access your project through API keys.

API keys provide the first layer of authentication for data access. Auth then builds upon that. This chart covers the differences:

Responsibility Question Answer
API keys What is accessing the project? Web page, mobile app, server, Edge Function...
Supabase Auth Who is accessing the project? Monica, Jian Yang, Gavin, Dinesh, Laurie, Fiona...

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:

Type Format Privileges Availability Use
Publishable key sb_publishable_... Low Platform Safe to expose online: web page, mobile or desktop app, GitHub actions, CLIs, source code.
Secret keys sb_secret_... Elevated Platform Only use in backend components of your app: servers, already secured APIs (admin panels), Edge Functions, microservices, etc. They provide full access to your project's data, bypassing Row Level Security.
anon JWT (long lived) Low Platform, CLI Exactly like the publishable key.
service_role JWT (long lived) Elevated Platform, CLI Exactly like secret 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, but if you want a specific key, you can find all keys in the API Keys section of a Project's Settings page:

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:

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.)

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:

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:

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:

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:

Your project's Security Advisor constantly checks for common security problems with the built-in Postgres roles. Make sure you carefully review each finding before dismissing it.

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:

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, 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:

Best practices for handling secret keys#

Below are some starting guidelines on how to securely work with secret keys:

What to do if a secret key or service_role has been leaked or compromised?#

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 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 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.

If you are still using the JWT-based service_role key, there are two options.

  1. Strongly recommended: Replace the service_role key with a new secret key instead. Follow the guide from above as if you are rotating an existing secret key.
  2. Rotate your project's JWT secret. This operation is only recommended if you suspect that the JWT secret has leaked itself. Consider switching your anon JWT-based key to the publishable key, and all service_role JWT-based keys to secret keys. Only then rotate the JWT secret. Check the FAQ below if you use the JWT-based keys in mobile, desktop or CLI applications!

As the publishable and secret keys are no longer JWT-based, there are some known limitations and compatibility differences that you may need to plan for:

I am using JWT-based anon key in a mobile, desktop, or CLI application and need to rotate my service_role JWT secret?#

If you know or suspect that the JWT secret itself is leaked, refer to the section on rotating the JWT.

If the JWT secret is secure, prefer substituting the service_role JWT-based key with a new secret key which you can create in the 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. 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.

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:

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:

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, Envoy, NGINX or similar.