Autenticação
O ProCases utiliza Steam OpenID 2.0 para autenticação, com sessões opacas no Redis (não JWT) para gerenciamento de estado e 2FA opcional (TOTP) para saques em dinheiro acima do threshold.
Visão Geral
┌─────────────────────────────────────────────────────────────────┐
│ FLUXO DE AUTENTICAÇÃO │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Steam │ │ Backend │ │ Redis │ │
│ │ OpenID │◄────►│ API │◄────►│ Sessions │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Dados │ │ Sessão │ │ TTL │ │
│ │ do Steam │ │ Criada │ │ 7 dias │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘Componentes do Sistema
1. Steam OpenID
- Login via conta Steam (OpenID 2.0, biblioteca
openid—RelyingParty) - Não armazenamos senhas
- Dados obtidos:
steamId,username,avatarUrl,profileUrl - Steam ID validado com regex de 17 dígitos (
^\d{17}$)
2. Sessions (Redis)
- Session ID de 32 bytes aleatórios (
randomBytes(32).toString('hex')→ 64 caracteres hex) - Armazenamento no Redis via
ioredis - TTL configurável por
SESSION_MAX_AGE(default604800= 7 dias) - Suporte a múltiplos dispositivos (Set
user:sessions:{userId}) - Revogação instantânea (session-based, não JWT)
3. 2FA (Two-Factor Authentication)
- TOTP (Time-based One-Time Password) via
speakeasy(secret base32,window: 1) - Google Authenticator / Authy compatível
- Obrigatório para saque em dinheiro acima do threshold (
WITHDRAWAL_2FA_THRESHOLD_CENTS, default R$ 100)
Fluxo Simplificado
1. Usuário clica "Login with Steam"
2. GET /api/auth/steam/login → redirect 302 para Steam
3. Steam autentica e retorna para STEAM_RETURN_URL
4. Backend valida a asserção OpenID (verifyAssertion)
5. SteamCallbackUseCase cria/atualiza usuário
6. Sessão criada no Redis + cookie sessionId
7. Redirect para {FRONTEND_URL}/auth/callback?success=true&sessionId=...
8. Usuário está logadoEndpoints
Prefixo real
As rotas de autenticação vivem sob @Controller('api/auth'). As rotas de 2FA não ficam em /api/auth — pertencem ao PaymentController (/payment/2fa/*), pois 2FA é usado no fluxo de saque.
| Método | Endpoint | Descrição |
|---|---|---|
| GET | /api/auth/steam/login | Inicia login Steam (redirect 302) |
| GET | /api/auth/steam/callback | Callback do Steam (valida asserção, cria sessão) |
| GET | /api/auth/me | Dados do usuário logado |
| POST | /api/auth/logout | Logout da sessão atual |
| POST | /api/auth/logout-all | Logout de todos os dispositivos |
| GET | /api/auth/sessions | Lista sessões ativas do usuário |
| DELETE | /api/auth/sessions/:sessionId | Revoga uma sessão específica (só do próprio usuário) |
| POST | /payment/2fa/setup | Gera secret + QR Code de 2FA |
| POST | /payment/2fa/enable | Ativa 2FA com verificação de token |
| POST | /payment/2fa/disable | Desativa 2FA (exige token) |
| POST | /payment/2fa/verify | Verifica um token 2FA |
Proteções de Segurança
| Proteção | Descrição |
|---|---|
| Session-based | Revogação instantânea (delete no Redis) |
| Session binding | Rejeita se IP ou User-Agent divergem da criação (anti-hijack) |
Cookie secure | Apenas HTTPS em produção |
| SameSite | none em produção, lax em dev |
| Rate limiting | 10 req/min em login e callback (@Throttle) |
| Redirect allowlist | isAllowedRedirect só aceita host do frontend/subdomínios |
| Username não sobrescrito | Re-login não altera o username (defesa contra impersonation via Steam API) |
| 2FA | TOTP obrigatório em saques de dinheiro acima do threshold |
Cookie sessionId não é HttpOnly
No callback, o cookie sessionId é setado com httpOnly: false — o frontend precisa ler o sessionId (também devolvido na query string do redirect) para reenviar via Authorization: Bearer em ambientes cross-site. A proteção contra hijack vem do session binding (IP + User-Agent), não do flag HttpOnly.
Diagrama de Estados
┌─────────────┐
│ Visitante │
│ (não logado)│
└──────┬──────┘
│ Login Steam
▼
┌─────────────┐
│ Logado │
│ (sessão │
│ ativa) │
└──────┬──────┘
│
├──────────────────┬──────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Logout │ │ Suspenso/ │ │ Binding │
│ (sessão │ │ Banido │ │ mismatch │
│ revogada) │ │ (status ≠ │ │ (401 no │
│ │ │ ACTIVE) │ │ AuthGuard) │
└─────────────┘ └─────────────┘ └─────────────┘Guard global
O AuthGuard é registrado como APP_GUARD (global). Toda request autenticada faz userRepository.findById(session.userId) e bloqueia se user.status !== 'ACTIVE'. Rotas públicas usam o decorator @Public().
Páginas desta Seção
- Steam OAuth - Fluxo completo de login (OpenID 2.0)
- Gestão de Sessões - Redis e múltiplos dispositivos
- 2FA (TOTP) - Autenticação de dois fatores
- Autorização Admin - Acesso ao painel admin
