Carregando recursos ...
rotas protegidas reactsupabase authreact routerautenticacao reactrow level securityvite

Rotas protegidas no React com Supabase Auth: guia prático

SCStormcore
5 min de leitura
Rotas protegidas no React com Supabase Auth: guia prático

Rotas protegidas no React com Supabase Auth: guia prático

Para criar rotas protegidas no React com Supabase Auth, você guarda a sessão do usuário em um contexto, escuta as mudanças de autenticação com onAuthStateChange e usa um componente que redireciona para o login quando não há sessão. Isso controla a navegação, mas a segurança real dos dados vem das políticas de Row Level Security (RLS) no banco, não do front-end.

Como funcionam as rotas protegidas no React

Em uma aplicação React com Vite, todo o código roda no navegador. Isso significa que qualquer pessoa pode abrir o DevTools e tentar acessar uma tela restrita. Por isso, uma rota protegida cumpre um papel de experiência do usuário: ela evita mostrar telas que ele não deveria ver e o leva ao login.

O fluxo básico tem três partes:

  1. Um provedor de autenticação que carrega e mantém a sessão.
  2. Um componente guardião que decide se renderiza a página ou redireciona.
  3. Políticas no banco que garantem que cada usuário só acesse os próprios dados.

Passo 1: criar o contexto de sessão com Supabase Auth

O cliente do Supabase oferece supabase.auth.getSession() para ler a sessão atual e supabase.auth.onAuthStateChange() para reagir a login, logout e renovação de token. Combine os dois em um contexto:

code
import { createContext, useContext, useEffect, useState } from 'react'
import { supabase } from './supabaseClient'

const AuthContext = createContext(null)

export function AuthProvider({ children }) {
  const [session, setSession] = useState(null)
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    supabase.auth.getSession().then(({ data }) => {
      setSession(data.session)
      setLoading(false)
    })

    const { data: listener } = supabase.auth.onAuthStateChange((_event, newSession) => {
      setSession(newSession)
    })

    return () => listener.subscription.unsubscribe()
  }, [])

  return (
    <AuthContext.Provider value={{ session, loading }}>
      {children}
    </AuthContext.Provider>
  )
}

export const useAuth = () => useContext(AuthContext)

O estado loading é essencial. Sem ele, o usuário logado é redirecionado ao login por alguns milissegundos enquanto a sessão ainda está sendo recuperada.

Passo 2: criar o componente de rota protegida com React Router

Com o contexto pronto, o guardião fica simples. Ele espera o carregamento, verifica a sessão e usa Navigate para redirecionar:

code
import { Navigate, Outlet, useLocation } from 'react-router-dom'
import { useAuth } from './AuthContext'

export function ProtectedRoute() {
  const { session, loading } = useAuth()
  const location = useLocation()

  if (loading) return <p>Carregando...</p>
  if (!session) return <Navigate to="/login" state={{ from: location }} replace />

  return <Outlet />
}

Guardar a rota de origem em state permite devolver o usuário à página que ele tentou acessar depois do login. Na configuração de rotas, basta agrupar as páginas restritas:

code
<Route element={<ProtectedRoute />}>
  <Route path="/painel" element={<Painel />} />
  <Route path="/perfil" element={<Perfil />} />
</Route>

Passo 3: a segurança de verdade está no RLS

Proteger a rota no React não protege os dados. A chave pública (anon) do Supabase fica exposta no navegador por design, e a documentação do Supabase deixa claro que a segurança deve ser aplicada com Row Level Security nas tabelas. Sem RLS, qualquer pessoa com a chave pode consultar a API diretamente.

Uma política simples para uma tabela de tarefas por usuário:

code
alter table public.tarefas enable row level security;

create policy "usuario ve suas tarefas"
on public.tarefas for select
using (auth.uid() = user_id);

Boas práticas para sua autenticação:

  • Ative o RLS em toda tabela exposta pela API.
  • Nunca coloque a chave service_role no front-end.
  • Trate o redirecionamento do React apenas como conveniência de navegação.
  • Para papéis de administrador, valide a permissão no banco, não apenas no cliente.

Erros comuns ao proteger rotas

O erro mais frequente é ignorar o estado de carregamento, causando um "pisca" de redirecionamento. Outro é guardar o papel do usuário em localStorage e confiar nele para liberar telas. Um terceiro é esquecer de cancelar a inscrição do onAuthStateChange ao desmontar o componente, o que gera vazamento de listeners.

Perguntas Frequentes

O que são rotas protegidas no React? São rotas que só renderizam o conteúdo se o usuário estiver autenticado. Caso contrário, o app redireciona para a página de login.

Rota protegida no React é suficiente para garantir segurança? Não. Ela só controla a navegação. A proteção dos dados precisa ser feita no servidor, no caso do Supabase, com políticas de Row Level Security.

Como saber se o usuário está logado no Supabase? Use supabase.auth.getSession() para ler a sessão atual e onAuthStateChange para acompanhar login e logout em tempo real.

Posso usar o mesmo padrão com Vite e Netlify? Sim. O padrão roda no cliente, então funciona em qualquer projeto React com Vite. Em SPAs no Netlify, lembre de configurar o redirecionamento para o index.html para que as rotas funcionem ao recarregar.

Conclusão

Rotas protegidas no React com Supabase Auth se resumem a um contexto de sessão, um componente guardião e, principalmente, RLS bem configurado no banco. Comece pelas políticas e depois cuide da navegação. Na Stormcore, desenvolvemos sites, sistemas e automações com esse stack, sempre com a segurança dos dados como prioridade.

Continue lendo

Matérias relacionadas

Pronto para tirar sua ideia do papel?

Fale agora com nosso time de desenvolvimento. Sites, apps, automações, o que você precisar.

Chamar no WhatsApp

Resposta em até 2 horas