Padrões de Autenticação Clerk
Guia Rápido: O Clerk fornece autenticação gerenciada com componentes de UI pré-construídos, helpers do lado do servidor e multi-tenancy baseado em organizações. Use
clerkMiddleware()para proteção de rotas,<Show>para renderização condicional, hooks para estado no cliente eauth()/currentUser()para autenticação no servidor. Clerk Core 3 (2026) substitui<SignedIn>/<SignedOut>por<Show>, renomeia o arquivo de middleware paraproxy.ts(Next.js 16+) e consolida pacotes.
<critical_requirements>
CRÍTICO: Antes de Usar Este Skill
Todo código deve seguir as convenções do projeto no CLAUDE.md (kebab-case, exportações nomeadas, ordenação de imports,
import type, constantes nomeadas)
(Você DEVE usar @clerk/nextjs/server para TODOS os imports do lado do servidor – NUNCA importe helpers de servidor de @clerk/nextjs)
(Você DEVE verificar webhooks usando o helper verifyWebhook do Clerk – NUNCA confie em payloads de webhook não verificados)
(Você DEVE usar o componente <Show> em vez dos obsoletos <SignedIn>/<SignedOut>/<Protect> – eles foram removidos no Core 3)
(Você NÃO DEVE passar o objeto completo currentUser() para o cliente – ele contém privateMetadata que deve permanecer no servidor)
(Você DEVE proteger as rotas TANTO no middleware QUANTO na camada de acesso a dados – apenas o middleware é insuficiente)
</critical_requirements>
Detecção automática: Clerk, ClerkProvider, clerkMiddleware, @clerk/nextjs, useUser, useAuth, useClerk, useSession, useOrganization, SignIn, SignUp, UserButton, UserProfile, OrganizationSwitcher, auth(), currentUser(), CLERK_SECRET_KEY, NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, Show when="signed-in"
Quando usar:
- Adicionar autenticação e gerenciamento de usuários a uma aplicação
- Construir aplicativos B2B multi-tenant com controle de acesso baseado em organizações
- Usar componentes de UI de login/cadastro pré-construídos com temas personalizáveis
- Proteger rotas com middleware e verificações de autorização no servidor
- Sincronizar dados de usuário do Clerk com seu banco de dados via webhooks
Padrões principais abordados:
- Configuração do ClerkProvider, variáveis de ambiente, configuração de middleware
- Componentes de UI pré-construídos (
<SignIn>,<SignUp>,<UserButton>,<Show>) - Hooks do lado do cliente (
useUser,useAuth,useSession,useOrganization) - Autenticação no servidor (
auth(),currentUser()) em Componentes Servidor, Manipuladores de Rota, Ações do Servidor - Proteção de rotas com middleware usando
clerkMiddleware()ecreateRouteMatcher() - Multi-tenancy baseado em organizações com papéis e permissões
- Manipulação de webhooks com verificação de assinatura Svix
Quando NÃO usar:
- Exigência de autenticação auto-hospedada (controle total sobre armazenamento de dados de autenticação)
- Não é possível usar um serviço de autenticação de terceiros (restrições de conformidade/regulamentação)
- Autenticação simples por chave de API (middleware personalizado é suficiente)
- Restrições orçamentárias impedem o uso de um serviço gerenciado
Recursos Detalhados:
- reference.md - Estruturas de decisão, referência rápida de hooks, guia de migração para Core 3
- examples/core.md - ClerkProvider, variáveis de ambiente, configuração de middleware
- examples/components.md - Componentes pré-construídos, personalização, propriedade appearance
- examples/hooks.md - useUser, useAuth, useSession, estados de carregamento, renderização condicional
- examples/server.md - Componentes Servidor, rotas de API, Ações do Servidor, manipulação de webhooks
- examples/organizations.md - Gerenciamento de organizações, papéis, permissões, RBAC
Filosofia
Clerk é uma plataforma de autenticação gerenciada que lida com todo o ciclo de vida da autenticação: cadastro, login, gerenciamento de sessão, perfis de usuário, organizações e MFA. Em vez de construir autenticação do zero, você integra o SDK e os componentes pré-construídos do Clerk.
Princípios fundamentais:
- Defesa em profundidade – Proteja as rotas na camada de middleware E verifique a autenticação em cada ponto de acesso a dados. Apenas o middleware é insuficiente (CVE-2025-29927 demonstrou vulnerabilidades de bypass de middleware).
- Autenticação primeiro no servidor – Use
auth()ecurrentUser()em Componentes Servidor e Manipuladores de Rota. Use hooks do cliente (useUser,useAuth) apenas quando precisar de estado reativo no cliente. - Pré-construído sobre personalizado – Use os componentes
<SignIn>,<SignUp>,<UserButton>do Clerk. Construa fluxos personalizados apenas quando os componentes pré-construídos realmente não puderem atender aos requisitos. - Organizações para multi-tenancy – Use Organizações do Clerk com papéis e permissões para aplicativos B2B. Não construa sistemas de tenant personalizados sobre o modelo de usuário do Clerk.
- Sincronização orientada por webhooks – Sincronize dados do Clerk com seu banco de dados via webhooks, não por polling. Sempre verifique as assinaturas dos webhooks com
verifyWebhook.
Quando usar Clerk:
- Você precisa de autenticação rapidamente com o mínimo de código personalizado
- Você deseja componentes de UI pré-construídos para login/cadastro/gerenciamento de usuário
- Você precisa de multi-tenancy baseado em organizações com RBAC
- Você deseja MFA gerenciado, SSO (SAML/OIDC) e login social
Quando NÃO usar Clerk:
- Você precisa de controle total sobre o armazenamento de dados de autenticação (exigência auto-hospedada)
- Você não pode usar um serviço de autenticação de terceiros (conformidade/regulamentação)
- Seu aplicativo precisa apenas de autenticação simples por chave de API
- Restrições orçamentárias impedem o uso de um serviço gerenciado
Padrões Principais
Padrão 1: Configuração do ClerkProvider e Middleware
Todo aplicativo Clerk precisa de <ClerkProvider> envolvendo o app e clerkMiddleware() protegendo as rotas. Veja examples/core.md para exemplos completos de configuração.
Regras principais:
ClerkProvidervai dentro de<body>, não envolvendo<html>– Core 3 exige isso- Use a variável de ambiente
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, nunca codifique chaves - O arquivo de middleware é
proxy.tsno Next.js 16+ oumiddleware.tsno Next.js <=15 - O endpoint de webhook deve estar na lista de rotas públicas (verificado separadamente por
verifyWebhook) CLERK_WEBHOOK_SIGNING_SECRETé a variável de ambiente para assinatura de webhook (nãoCLERK_WEBHOOK_SECRET)
// proxy.ts (Next.js 16+) ou middleware.ts (Next.js <=15)
const isPublicRoute = createRouteMatcher([
"/",
"/sign-in(.*)",
"/sign-up(.*)",
"/api/webhooks(.*)",
]);
export default clerkMiddleware(async (auth, req) => {
if (!isPublicRoute(req)) {
await auth.protect();
}
});
Por que é bom: Rotas públicas explicitamente na lista de permissões, todo o resto requer autenticação, endpoint de webhook é público (verificado separadamente)
// RUIM: clerkMiddleware() sem callback
export default clerkMiddleware(); // TODAS as rotas são PÚBLICAS por padrão!
Por que é ruim: clerkMiddleware() sem callback anexa dados de autenticação mas não protege nenhuma rota
Padrão 2: Componentes de UI Pré-construídos e <Show>
Use <Show> para renderização condicional (substituto do Core 3 para <SignedIn>/<SignedOut>/<Protect>). Veja examples/components.md para exemplos completos.
<Show when="signed-out"><SignInButton /></Show>
<Show when="signed-in"><UserButton /></Show>
<Show when={{ role: "org:admin" }}><AdminPanel /></Show>
<Show when={(has) => has({ permission: "org:invoices:manage" })}><InvoiceManager /></Show>
Por que é bom: <Show> é a API do Core 3, suporta condições string/objeto/callback, prop fallback para não autorizado
// RUIM: Obsoleto – removido no Core 3
<SignedIn>...</SignedIn>
<SignedOut>...</SignedOut>
<Protect role="admin">...</Protect>
Por que é ruim: <SignedIn>, <SignedOut>, <Protect> removidos no Core 3, use <Show> com a prop when
Páginas de login/cadastro exigem segmentos de rota catch-all [[...sign-in]] para fluxos de várias etapas (MFA, callbacks OAuth).
Padrão 3: Hooks do Lado do Cliente
Use hooks em Componentes Cliente para estado de autenticação reativo. Sempre verifique isLoaded antes de acessar os dados. Veja examples/hooks.md para exemplos completos.
"use client";
const { isLoaded, isSignedIn, user } = useUser();
if (!isLoaded) return <div>Carregando...</div>;
if (!isSignedIn) return <div>Por favor, faça login</div>;
// Agora é seguro acessar user.firstName, user.emailAddresses, etc.
Por que é bom: Previne erros de hidratação ao acessar undefined durante a inicialização, previne TypeError ao acessar null quando desconectado
// RUIM: Acessando user sem guardas
const { user } = useUser();
return <p>{user.firstName}</p>; // Erro em tempo de execução quando isLoaded=false ou isSignedIn=false
Por que é ruim: user é undefined até carregar e null quando desconectado
Hooks principais:
useUser()– dados do perfil do usuário (nome, email, avatar)useAuth()– tokens de sessão (getToken()),userId,orgId,has()para autorizaçãouseOrganization()– dados da organização ativa, associação, lista paginada de membrosuseReverification()– re-autenticar antes de ações sensíveis (Core 3)
No Core 3, getToken() lança ClerkOfflineError quando offline em vez de retornar null – sempre envolva em try/catch.
Padrão 4: Autenticação no Lado do Servidor
Use auth() e currentUser() de @clerk/nextjs/server. Veja examples/server.md para exemplos completos.
auth() – leve, sem chamada de API, lê claims da sessão:
import { auth } from "@clerk/nextjs/server";
const { userId, orgId, isAuthenticated, redirectToSignIn } = await auth();
if (!isAuthenticated) return redirectToSignIn();
currentUser() – objeto de usuário completo, faz chamada à API Backend:
import { currentUser } from "@clerk/nextjs/server";
const user = await currentUser();
// CRÍTICO: Selecione campos seguros antes de passar para componentes cliente
const safeData = { firstName: user.firstName, imageUrl: user.imageUrl };
Por que é crítico: currentUser() retorna privateMetadata que nunca deve chegar ao cliente. Selecione campos explicitamente.
Defesa em profundidade: A autenticação DEVE ser verificada em cada Ação do Servidor e Manipulador de Rota, não apenas no middleware:
"use server";
const { userId } = await auth();
if (!userId) throw new Error("Não autorizado");
// userId escopo de todas as consultas/mutações para o usuário atual
Padrão 5: Autorização com Papéis e Permissões
Use auth.protect() ou has() para controle de acesso granular. Veja examples/organizations.md para padrões RBAC.
// Middleware: proteção de rota baseada em papel
await auth.protect((has) => has({ role: "org:admin" }));
// Componente Servidor: verificação de permissão
const { has } = await auth();
if (!has({ permission: "org:invoices:delete" })) redirect("/dashboard");
// Cliente: renderização condicional por papel
<Show when={{ role: "org:admin" }}><AdminPanel /></Show>
Formato de permissão: org:<feature>:<action> (ex.: org:invoices:create, org:reports:read)
Papéis padrão: org:admin (todas as permissões), org:member (somente leitura). Papéis personalizados configurados no Painel do Clerk.
Padrão 6: Manipulação de Webhooks
Use webhooks do Clerk (via Svix) para sincronizar dados de usuário com seu banco de dados. Veja examples/server.md para o manipulador completo.
import { verifyWebhook } from "@clerk/nextjs/webhooks";
export async function POST(req: Request) {
const evt = await verifyWebhook(req); // lê a variável de ambiente CLERK_WEBHOOK_SIGNING_SECRET
// evt.type: "user.created" | "user.updated" | "user.deleted" | "organization.*" | ...
// evt.data: UserJSON | OrganizationJSON | etc.
}
Por que é bom: verifyWebhook valida a assinatura Svix, sempre retorna 200 para evitar novas tentativas, a rota de webhook é pública no middleware (verificada pela assinatura, não pela autenticação)
// RUIM: Sem verificação de assinatura
const body = await req.json(); // Qualquer um pode POSTAR dados falsos!
await db.insert(users).values(body.data); // Vulnerabilidade de segurança
Por que é ruim: Nenhuma verificação de assinatura significa que qualquer um pode enviar eventos de webhook falsos para seu endpoint
Importe tipos de @clerk/shared/types (Core 3): UserJSON, OrganizationJSON, OrganizationMembershipJSON
<decision_framework>
Estrutura de Decisão
Autenticação Cliente vs Servidor
Onde você precisa de dados de autenticação?
|-- Componente Servidor, Manipulador de Rota, Ação do Servidor
| |-- Precisa apenas de userId/sessionId? --> auth()
| |-- Precisa do objeto de usuário completo? --> currentUser()
| |-- Precisa proteger a rota? --> auth.protect()
| +-- Precisa de contexto de organização? --> auth() retorna orgId, orgRole
|
+-- Componente Cliente (UI interativa)
|-- Precisa de dados do perfil do usuário? --> useUser()
|-- Precisa de dados de sessão/token? --> useAuth()
|-- Precisa de dados da organização? --> useOrganization()
+-- Precisa da API Clerk de baixo nível? --> useClerk()
Estratégia de Proteção de Rotas
Que tipo de rota é?
|-- Pública (landing, login, cadastro, webhooks)
| +-- Adicione ao matcher isPublicRoute, pule auth.protect()
|
|-- Autenticada (painel, perfil, configurações)
| +-- auth.protect() no middleware + verificação auth() na camada de dados
|
+-- Autorizada (admin, específica de organização, com portão de permissão)
|-- Baseada em papel? --> auth.protect({ role: "org:admin" })
+-- Baseada em permissão? --> auth.protect((has) => has({ permission: "org:feature:action" }))
Escolha de Componente
De qual UI de autenticação você precisa?
|-- Página de login completa --> <SignIn /> em rota catch-all
|-- Página de cadastro completa --> <SignUp /> em rota catch-all
|-- Botão de login (modal) --> <SignInButton />
|-- Avatar do usuário + menu --> <UserButton />
|-- Editor de perfil completo --> <UserProfile />
|-- Alternador de organização --> <OrganizationSwitcher />
+-- Conteúdo condicional --> <Show when="signed-in"> ou <Show when={{ role: "..." }}>
</decision_framework>
<red_flags>
SINALIZADORES VERMELHOS
Problemas de Alta Prioridade:
- Importar helpers de servidor de
@clerk/nextjsem vez de@clerk/nextjs/server(quebra em Componentes Servidor) - Usar componentes obsoletos
<SignedIn>/<SignedOut>/<Protect>(removidos no Core 3) - Passar o objeto completo
currentUser()para componentes cliente (vazaprivateMetadata) - Confiar em payloads de webhook sem verificação de assinatura
verifyWebhook - Depender apenas do middleware para proteção de rotas (middleware pode ser contornado)
- Importar tipos de
@clerk/typesem vez de@clerk/shared/types(mudança no Core 3) - Usar formatação camelCase para nomes de arquivos/constantes quando o projeto usa kebab-case
Problemas de Média Prioridade:
- Ignorar o estado
isLoadedem hooks do cliente (causa erros de tempo de execução) - Não tratar offline em
getToken()(Core 3 lançaClerkOfflineError) - Colocar
ClerkProviderem volta de<html>(posicionamento incorreto no Core 3) - Usar
CLERK_WEBHOOK_SECRETem vez deCLERK_WEBHOOK_SIGNING_SECRET - Esquecer de adicionar a rota de webhook às rotas públicas no middleware
- Não selecionar campos seguros de
currentUser()antes de passar para o cliente
Sempre verifique o CLAUDE.md para convenções específicas do projeto antes de escrever código.
</red_flags>