Pular para o conteúdo

Noções de segurança

Onde ficam as chaves de API do Supabase: anon, service_role e URL

A URL do projeto, a chave anon e a chave service_role ficam todas numa página do painel. Aqui está onde ela fica, e qual dos quatro valores vai no seu app.

Vlad Tkachenko10 min de leitura
Um painel de configurações: uma URL e uma chave anon à mostra, uma chave service_role e um valor JWT escondidos atrás de pontinhos.

Em resumo

  • Toda chave do Supabase, service_role incluída, fica numa página só: abra seu projeto no painel e depois Settings → API Keys.
  • Lá ficam quatro valores. A URL do projeto e a chave publicável vão no seu app; a chave secreta e o valor JWT nunca.
  • Essa página diz quais chaves existem. Ela não diz qual delas foi parar no seu app, e só a segunda pergunta pode te machucar.

Alguma coisa pediu a sua chave do Supabase. Um guia de instalação, uma thread de suporte, ou uma IA para quem você mandou consertar o seu app. Você abre o painel, encontra uma página com um endereço e duas ou três chaves com nomes como anon e service_role, e cada uma delas parece que pode ser a resposta.

Ou é a outra versão disso. Alguém abriu o seu site, apertou F12 e disse que uma chave está exposta. Agora você quer olhar a chave que essa pessoa encontrou, e não sabe onde ela mora.

A maioria dos guias começa na página de chaves de API. Isso pressupõe que você já saiba qual projeto do Supabase é o seu, e esse é exatamente o passo que um builder fez por você e nunca explicou.

Onde ficam as chaves de API do Supabase?

No painel, dentro do seu projeto, em Settings → API Keys.

O caminho inteiro: entre no supabase.com, escolha o seu projeto na lista, abra Settings na barra lateral esquerda e depois API Keys. Quase todo guia e toda captura de tela que você vai achar chamam essa página de Settings → API, porque era assim que ela se chamava até pouco tempo atrás. É a mesma página e são os mesmos valores.

Tudo que está nela é uma de duas coisas. Um endereço, que diz onde o seu projeto mora. Ou uma chave, que decide o que uma requisição pode fazer depois que chega. A página lista as duas coisas juntas, numa coluna só, na mesma tipografia.

Eu nunca configurei o Supabase. Qual projeto é o meu?

Leia o endereço que o seu app já está usando. A resposta está dentro dele.

Todo projeto do Supabase tem uma referência: uma string curta e aleatória que também é a primeira parte do endereço do projeto, https://yourreference.supabase.co. O seu app manda uma requisição para esse endereço a cada carregamento de página, então a string já está dentro do seu app, e é a mesma com que o painel identifica o seu projeto.

Três lugares onde achá-la sem perguntar a ninguém:

  • No seu builder. Lovable, Bolt, v0 e os outros mostram o projeto do Supabase conectado em algum lugar nas configurações ou no painel de integrações do seu projeto.
  • No seu navegador. Abra o seu app no ar, aperte F12, vá para a aba Network e recarregue a página. As requisições que saem para alguma coisa com .supabase.co carregam a referência no próprio endereço.
  • No código-fonte da página, se o seu app escreve o endereço no HTML em vez de num arquivo de script.

Depois entre no supabase.com e compare essa referência com a sua lista de projetos. Os builders conectam o Supabase pela sua própria conta, então o projeto costuma estar num painel em que você se cadastrou uma vez e nunca usou. Assim que você entra num projeto a referência aparece na barra de endereços do navegador, e é assim que você confirma que está no projeto certo antes de copiar qualquer coisa dele.

As quatro coisas dessa página

Um endereço e três chaves. Duas vão no seu app e duas nunca saem do painel.

O que você vêO que éPara onde vaiSe vazar
Project URLO endereço do seu projeto, https://yourreference.supabase.co. Diz onde, nunca quem.No seu appNada. Ela já vai para todo visitante a cada carregamento de página.
Publishable key sb_publishable_…Diz qual é o projeto e não carrega permissão própria nenhuma. Chama-se anon num projeto antigo.No seu appNada sozinha. Ela lê exatamente o que as suas regras de Row Level Security permitem.
Secret key sb_secret_…Lê e escreve cada linha de cada tabela, digam o que disserem as suas regras. Chama-se service_role num projeto antigo.Só no servidorCada linha de cada tabela, para quem tiver achado.
JWT secretAssina os tokens que dizem quem está logado. Chama-se JWT signing keys num projeto novo.Fica no SupabaseAlguém pode emitir um token afirmando ser qualquer um dos seus usuários, inclusive um administrador.
Quatro valores, uma página. O Supabase não desenha linha nenhuma entre eles, e a máscara sobre os dois de baixo é a única pista que você ganha.

Existe um atalho na própria página. O Supabase imprime a URL do projeto e a chave publicável onde você consegue ler, e cobre a chave secreta e o valor JWT com pontinhos até você pedir para ver. As duas que ele cobre são justamente as duas que nunca vão no seu app.

Onde fica a URL do meu projeto Supabase?

Em dois lugares, e você provavelmente já está olhando para um deles. O painel imprime ela no topo de Settings → API Keys, com o rótulo Project URL. A barra de endereços do seu navegador mostra a mesma string sempre que o seu app fala com o Supabase, no formato https://yourreference.supabase.co.

No código ela usa um de três nomes, e os três guardam essa mesma string:

  • VITE_SUPABASE_URL num app construído com Vite, que cobre a maior parte do que Lovable e Bolt produzem
  • NEXT_PUBLIC_SUPABASE_URL num app Next.js
  • SUPABASE_URL num servidor, numa edge function ou num script

O meio dela, yourreference, é a referência do seu projeto. É a string pela qual o painel identifica o projeto, e a que você compara quando tem vários projetos e nenhuma ideia de qual pertence a este app.

É um endereço mais do que um segredo, e é por isso que fica à vista ao lado da chave publicável.

Onde fica a chave service_role, e o que é SUPABASE_SERVICE_ROLE_KEY?

Na mesma página que todo o resto. Abra Settings → API Keys e procure a linha service_role, ou secret num projeto criado recentemente. Diferente da URL e da chave publicável, o valor dela fica atrás de um controle de revelar até você pedir.

Esse controle é a única pista que o painel dá de que essa aqui é diferente, e vale levar a sério: o Supabase cobre exatamente os valores que nunca podem chegar a um navegador.

SUPABASE_SERVICE_ROLE_KEY é um nome de variável mais do que uma segunda chave: atrás dele está o valor que você acabou de revelar. Você vai encontrar num arquivo .env, nas configurações de ambiente da sua hospedagem, ou nos segredos de uma edge function. O que importa é o prefixo na frente. Uma variável chamada VITE_SUPABASE_SERVICE_ROLE_KEY ou NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY é compilada dentro do JavaScript que seus visitantes baixam, então a chave fica pública no momento em que você faz o deploy. Esses prefixos são instruções de publicar, não descuidos.

Onde ela cabe é numa edge function, num handler de webhook, num job agendado ou num script de migração: em qualquer lugar onde o código roda numa máquina que você controla e nenhum visitante pode abrir o arquivo. Essa é a chave que ignora Row Level Security por completo, então lê cada linha de cada tabela digam o que disserem as suas regras.

Se você não tem certeza de que a sua ficou no servidor, o nosso verificador de segurança de sites grátis lê o seu site no ar por fora e nomeia as chaves que encontra, em uns 20 segundos.

De qual chave o meu app precisa?

Da URL do projeto e da chave publicável. Nada mais, nunca.

O seu app roda no navegador dos seus visitantes e fala com o Supabase de lá, então os dois valores vão para todo visitante por construção. Isso não é um vazamento e nunca foi. O que impede um desconhecido de ler o seu banco inteiro com uma chave publicável é o Row Level Security: as regras que decidem, linha por linha, quem pode ver o quê.

Então são essas regras que você precisa conferir quando fica preocupado, e ligá-las não é a mesma coisa que estar protegido. A versão longa de por que uma chave é segura em público está em quais chaves de API são seguras no frontend.

Como eu sei qual chave o meu app levou de verdade?

Pelo painel você não descobre. Ele lista as chaves que o seu projeto tem, não a que foi parar dentro do seu app.

São duas perguntas diferentes, e só a segunda pode te machucar. Um projeto pode ter uma página de configurações completamente comum e mesmo assim ter a chave secreta colada num arquivo que qualquer um consegue abrir. Para responder isso você tem que ler a chave que está de fato no app.

Num projeto novo, leia os primeiros caracteres. sb_publishable_ é a que pertence ali. sb_secret_ é a que precisa de atenção hoje.

Num projeto antigo, você tem que olhar dentro da chave. anon e service_role são JWT: três blocos separados por pontos, e o do meio decodifica para texto perfeitamente legível. Ele carrega um campo role, e essa única palavra é toda a diferença entre as duas. Como ler isso.

O painel mostra quais chaves existem. Qual delas o seu app levou é uma pergunta que só o seu app pode responder.

Se você prefere não passar o seu app na mão, o nosso scan gratuito lê o seu site no ar por fora e diz quais chaves ele consegue ver, junto com se as suas tabelas respondem a um desconhecido que pergunta. Leva uns 20 segundos e não precisa de conta: escanear seu app.

E se a chave secreta já estiver no meu app?

Resolva a chave em si antes de mexer em qualquer código, e no Supabase isso pode não significar o que você espera.

O conselho de sempre é rotacionar: gerar uma chave nova, revogar a antiga, e o valor que vazou para de funcionar. Isso continua valendo para as chaves novas. Um projeto pode ter várias chaves sb_secret_ ao mesmo tempo e revogá-las uma de cada vez, então trocar uma não significa mais um minuto em que tudo que a usava está quebrado.

Para o par original não vale de jeito nenhum. As próprias notas de solução de problemas do Supabase dizem que não é mais possível rotacionar os antigos segredos anon, service_role e JWT. Inutilizar uma chave service_role antiga que vazou passa por criar as chaves novas, mover seu app e seu código de servidor para elas, e só então desativar o par antigo. O que essa migração envolve são alguns passos no painel e um valor trocado no seu app, o que é bem mais tranquilo numa tarde calma do que no dia em que você precisa.

O que fazer agora

O que fazer

  • Abra Settings → API Keys dentro do seu projeto. Se você não achar o projeto, tire a referência de https://yourreference.supabase.co e compare com a lista do seu painel.
  • Coloque a URL do projeto e a chave publicável no seu app. Essas duas, e nada mais.
  • Leia a chave que o seu app levou de verdade. sb_secret_ na frente, ou "role": "service_role" dentro de uma antiga, é o achado para tratar hoje.
  • Se tem uma chave secreta no seu frontend, inutilize antes de editar qualquer coisa. Num projeto antigo isso quer dizer criar as chaves novas e desativar o par antigo, e não existe um botão único para isso.
  • Dê uma olhada no Row Level Security já que você está no painel. Uma chave publicável só é segura por causa dessas regras, e sem elas ela lê o seu banco inteiro.

Se você prefere fazer isso como uma lista, o checklist de segurança de 10 minutos cobre isso e as outras coisas que vale desligar num app recém-lançado, e temos um guia em linguagem simples para apps Supabase.

Perguntas frequentes

Onde fica a chave service_role no Supabase?

No painel, dentro do seu projeto, em Settings → API Keys. Num projeto antigo ela aparece com o nome service_role e fica escondida atrás de um botão para exibir; num projeto novo é uma chave secreta que começa com sb_secret_. Guias mais antigos chamam a mesma página de Settings → API.

Como é uma chave anon do Supabase?

Num projeto novo é uma string longa que começa com sb_publishable_. Num projeto antigo é um JWT: três blocos de caracteres separados por pontos, começando com eyJ, e com algumas centenas de caracteres no total. A chave service_role tem exatamente a mesma cara, e é por isso que as duas são confundidas.

A URL do meu projeto no Supabase é segredo?

Não. É o endereço para onde seu app manda cada requisição, então ela vai para todo visitante por construção e não existe versão do seu app em que ela esteja escondida. Encontrá-la não é um achado. Quem decide se um desconhecido consegue ler seus dados é o Row Level Security, não o fato de ele saber seu endereço.

Meu app foi construído para mim e eu nunca abri o Supabase. Como eu entro?

Ache primeiro a referência do seu projeto: a string curta e aleatória dentro do endereço que seu app já chama, https://yourreference.supabase.co. Os builders conectam o Supabase pela sua própria conta, então o projeto costuma estar num painel em que você se cadastrou uma vez e nunca usou. Entre no supabase.com com essa conta e compare a referência com a lista de projetos.

Dá para rotacionar uma chave service_role que vazou?

Só se for uma das novas chaves sb_secret_, das quais você pode ter várias e revogar uma de cada vez. O Supabase disse que não é mais possível rotacionar os antigos segredos anon, service_role e JWT. Inutilizar uma chave antiga que vazou passa por criar as chaves novas, mover seu app e seu código de servidor para elas, e só então desativar o par antigo.

O que é SUPABASE_SERVICE_ROLE_KEY?

É o nome de variável de ambiente com que o seu código guarda a chave secreta, aquela que aparece como service_role num projeto antigo e como sb_secret_ num mais novo. O lugar dela é só a configuração do lado do servidor: uma edge function, um handler de webhook, um job agendado. Qualquer coisa com prefixo VITE_ ou NEXT_PUBLIC_ é compilada dentro do bundle do navegador, então uma chave service_role atrás de um desses nomes fica pública no momento do deploy.

Escrito por

Vlad Tkachenko

Fundador da Reeve

Passo meus dias olhando apps criados com Lovable, Bolt, v0, Cursor e Replit, e a curta lista de erros que aparecem neles sem parar.

Mais sobre o autor

Leia depois

Todos os artigos

Não sabe como está o seu próprio app?

Faça um scan gratuito e receba uma nota clara de A a F em cerca de 20 segundos. Sem conta e sem cartão.

Verificar meu app grátis

Verificação externa automatizada, não uma auditoria completa. A ausência de achados não é garantia de segurança.