Appearance
Autenticação e Autorização
Fluxo de autenticação OAuth e controle de acesso.
Fluxo OAuth
IMPORTANTE: A URL OAuth é construída no frontend, não no backend.
┌────────┐ ┌─────────┐ ┌──────────┐ ┌────────┐
│Frontend│ │ Backend │ │ Provider │ │Database│
└───┬────┘ └────┬────┘ └────┬─────┘ └───┬────┘
│ │ │ │
│ Frontend constrói URL OAuth │ │
│═══════════════════════════════► │
│ Popup abre Provider │ │
│ │ │ │
│◄══════════════════════════════│ │
│ Callback com code │ │
│ │ │ │
│ POST /auth/social │ │
│ { provider, code } │ │
│──────────────►│ │ │
│ │ Exchange code │ │
│ │──────────────►│ │
│ │◄─ Token ──────│ │
│ │ Get profile │ │
│ │──────────────►│ │
│ │◄─ Profile ────│ │
│ │ │ │
│ │ Upsert user │ │
│ │──────────────────────────────►│
│ │◄──────────────────────────────│
│ │ │ │
│◄─ { user, token, companies, │ │
│ action, needsProfileCompletion } │
│ │ │ │Endpoints de Autenticação
| Endpoint | Método | Descrição |
|---|---|---|
/auth/social | POST | Autentica com código OAuth |
/auth/complete-profile | POST | Completa dados do perfil |
/auth/create-company | POST | Cria nova empresa |
/auth/me | GET | Dados do usuário autenticado |
/auth/companies | GET | Lista empresas do usuário |
/auth/logout | POST | Realiza logout |
Response do /auth/social
typescript
{
user: User,
token: string,
companies: Company[],
action: 'login' | 'register',
needsProfileCompletion: boolean
}JWT Payload
typescript
interface IJwtPayload {
sub: string; // User ID
sid?: string; // App device-session id (somente tokens do app mobile)
email: string;
name: string;
iat: number;
exp: number;
}Guards
JwtAuthGuard
Valida token JWT em todas as rotas (aplicado globalmente). Quando o payload tem o claim sid (tokens do app mobile), o JwtStrategy também valida a sessão de dispositivo: se a linha em app_device_sessions não existe ou está revogada (revokedAt), recusa com 401 "Dispositivo desconectado". Tokens web não têm sid e seguem o fluxo normal. É o que permite ao painel desconectar um aparelho de verdade (revogação que invalida o token na próxima requisição). Endpoints e tabela em api/app-devices.md.
CompanyGuard
Valida o header x-company-id e verifica se o usuário tem acesso à empresa.
SigningJwtGuard
Guard separado do JwtAuthGuard, aplicado apenas em /signing/:token. Extrai o JWT da URL (não do header Authorization), valida:
- Assinatura e expiração com
authConfig.jwt.secret(HS256). - Claim
type === "signing": recusa JWTs de outros tipos (login, reset, convite). contract.status: recusa signing em contratosCOMPLETED / FINISHED / OVERDUE / ACTIVE.
Injeta SigningContext { contractId, signerId } no request.signing, consumido via @GetSigningContext(). As rotas sob /signing/:token usam @Public() + @SkipCompany() para bypass dos guards padrão.
JWT Payload de assinatura
typescript
interface SigningTokenPayload {
contractId: string;
signerId: string;
type: 'signing';
iat: number;
exp: number;
}Decorators
| Decorator | Uso |
|---|---|
@Public() | Marca rota como pública (sem autenticação) |
@SkipCompany() | Pula validação de empresa |
@CurrentUser() | Extrai dados do usuário autenticado |
@CurrentCompany() | Extrai dados da empresa do contexto |
Header x-company-id
Todas as rotas que requerem contexto de empresa devem enviar:
x-company-id: <uuid-da-empresa>O guard valida:
- Presença do header
- Usuário tem acesso à empresa (borrower, provider ou user)
Documento atualizado em Janeiro 2026