Skip to content

Autenticação com Clerk

Como funciona

O CRM usa o Clerk como provedor de autenticação. O Clerk gerencia:

  • Login / cadastro de usuários
  • Sessões e tokens JWT
  • Organização de usuários (multi-tenancy no Clerk)
  • Webhooks de ciclo de vida (usuário criado/atualizado/deletado)

Fluxo de autenticação

1. Usuário faz login no frontend (crm.galdix.com.br)
   └─ Clerk SDK autentica (email/senha, SSO)
   └─ Clerk retorna JWT para o browser

2. Frontend inclui JWT no header de cada request:
   Authorization: Bearer <clerk_jwt>

3. Backend (ClerkAuthGuard):
   └─ Extrai token do header Authorization
   └─ Chama clerkClient.verifyToken(token)
   └─ Clerk SDK valida assinatura + expiração
   └─ Extrai sub (Clerk User ID) do payload
   └─ Busca usuário no banco por clerkId
   └─ Se não encontrado: auto-sync com Clerk API

4. Usuario é anexado em request.user
   └─ Contém: id, email, role, organizationId, accessibleStores

5. TenantInterceptor:
   └─ Define organizationId no AsyncLocalStorage
   └─ Todas as queries subsequentes usam esse organizationId

Auto-sync no primeiro login

Se o usuário faz login mas não existe no banco local:

  1. Busca dados do usuário na Clerk API
  2. Cria ou atualiza registro local
  3. Associa ao papel e organização corretos
  4. Permite acesso (não bloqueia)

Webhooks do Clerk

O Clerk envia webhooks para POST /webhooks/clerk quando há mudanças de usuário.

Verificação: Headers Svix (svix-id, svix-timestamp, svix-signature) validados com CLERK_WEBHOOK_SECRET.

Eventos tratados:

EventoAção
user.createdSync do novo usuário
user.updatedAtualiza dados
user.deletedRemove do banco
invitation.revokedRemove convite pendente
organization_membership.deletedRemove da organização

Endpoints públicos

Marcados com @Public() no código — ignoram ClerkAuthGuard:

typescript
@Public()
@Get('/public/survey/respond')
async respond() { ... }

Bootstrap de sincronização

Na inicialização do backend, o ClerkBootstrapService sincroniza todas as organizações e membros do Clerk com o banco local. Esse processo é não-fatal — falhas são logadas mas não impedem o boot.

Roles padrão criados automaticamente

Por organização, na criação:

  • Super Admin (level 0) — acesso total
  • Usuário (level 2) — papel padrão para novos membros

Mapeamento Clerk → Role local:

  • org:admin no Clerk → Super Admin
  • org:member no Clerk → Usuário padrão

Convites

Fluxo via POST /users/invite:

  1. Cria convite na organização Clerk
  2. Cria usuário local com status = 'INVITED' e clerkInvitationId
  3. Clerk envia email automaticamente
  4. Usuário clica no link → signup na URL {FRONTEND_URL}/sign-up
  5. Webhook user.created → auto-sync completa o registro

Reset de senha

POST /users/:id/reset-password:

  • Revoga todas as sessões ativas do usuário no Clerk
  • Usuário precisa usar "Forgot Password" no próximo login
  • Ação é auditada (action: ADMIN_PASSWORD_RESET)