Autenticação da API
Tarefa AI utiliza um sistema de autenticação híbrido baseado em cookies de sessão HTTP-only e JWT tokens para máxima segurança. Todos os endpoints da API requerem autenticação, exceto os endpoints públicos explicitamente marcados.
Visão Geral
Métodos de Autenticação
- Cookies de Sessão: Padrão para aplicação web (recomendado)
- Bearer Token: Para integrações via API e mobile
- OAuth 2.0: Google, GitHub (em implementação)
Segurança
- Cookies
httpOnlyesecure(HTTPS only em produção) - Sessões com expiração de 7 dias
- Rate limiting em endpoints de autenticação
- Tokens CSRF para proteção contra ataques
- Senhas hasheadas com bcrypt (cost factor 10)
Fluxo de Autenticação
1. Registro de Usuário
interface RegisterRequest {
name: string;
email: string;
password: string;
timezone?: string;
}
interface RegisterResponse {
success: boolean;
user: {
id: number;
email: string;
name: string;
createdAt: string;
};
}Endpoint: POST /api/auth/register
Request:
curl -X POST https://api.tarefaai.com/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"name": "João Silva",
"email": "joao@example.com",
"password": "SenhaSegura123!",
"timezone": "America/Sao_Paulo"
}'Response (201 Created):
{
"success": true,
"user": {
"id": 123,
"email": "joao@example.com",
"name": "João Silva",
"createdAt": "2025-01-17T10:00:00.000Z"
}
}Validações:
- Nome: 2-100 caracteres
- Email: formato válido, único no sistema
- Senha: mínimo 8 caracteres, deve conter maiúscula, minúscula e número
Erros:
// 400 - Validação falhou
{
"success": false,
"error": "Validation error",
"details": {
"password": ["Senha deve conter maiúscula, minúscula e número"]
}
}
// 409 - Email já cadastrado
{
"success": false,
"error": "Email já cadastrado"
}2. Login
interface LoginRequest {
email: string;
password: string;
}
interface LoginResponse {
success: boolean;
user: {
id: number;
email: string;
name: string;
role: "USER" | "ADMIN";
};
token?: string; // Apenas se solicitado via header
}Endpoint: POST /api/auth/login
Request:
curl -X POST https://api.tarefaai.com/api/auth/login \
-H "Content-Type: application/json" \
-c cookies.txt \
-d '{
"email": "joao@example.com",
"password": "SenhaSegura123!"
}'Response (200 OK):
{
"success": true,
"user": {
"id": 123,
"email": "joao@example.com",
"name": "João Silva",
"role": "USER"
}
}Headers de Resposta:
Set-Cookie: local-session=123; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=604800Para obter Bearer Token (integrações API):
curl -X POST https://api.tarefaai.com/api/auth/login \
-H "Content-Type: application/json" \
-H "X-Request-Token: true" \
-d '{
"email": "joao@example.com",
"password": "SenhaSegura123!"
}'Response com Token:
{
"success": true,
"user": {
"id": 123,
"email": "joao@example.com",
"name": "João Silva",
"role": "USER"
},
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}Erros:
// 401 - Credenciais inválidas
{
"success": false,
"error": "Email ou senha inválidos"
}
// 429 - Rate limit excedido
{
"success": false,
"error": "Muitas tentativas de login. Tente novamente em 15 minutos."
}3. Logout
Endpoint: POST /api/auth/logout
Request:
curl -X POST https://api.tarefaai.com/api/auth/logout \
-H "Cookie: local-session=123"Response (200 OK):
{
"success": true,
"message": "Logout realizado com sucesso"
}Headers de Resposta:
Set-Cookie: local-session=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0Recuperação de Senha
1. Solicitar Reset de Senha
Endpoint: POST /api/auth/forgot-password
interface ForgotPasswordRequest {
email: string;
}Request:
curl -X POST https://api.tarefaai.com/api/auth/forgot-password \
-H "Content-Type: application/json" \
-d '{
"email": "joao@example.com"
}'Response (200 OK):
{
"success": true,
"message": "Se o email existir, você receberá um link de redefinição"
}Nota de Segurança: O endpoint sempre retorna sucesso para prevenir enumeração de emails.
O que acontece:
- Sistema gera token único de 64 caracteres
- Token válido por 1 hora
- Email enviado com link de reset:
https://app.tarefaai.com/handler/reset-password/{token}
2. Validar Token de Reset
Endpoint: GET /api/auth/validate-reset-token?token={token}
Request:
curl -X GET "https://api.tarefaai.com/api/auth/validate-reset-token?token=abc123..."Response (200 OK):
{
"valid": true,
"userId": 123
}Erros:
// 400 - Token inválido
{
"valid": false,
"error": "Token inválido"
}
// 400 - Token expirado
{
"valid": false,
"error": "Token expirado"
}
// 400 - Token já utilizado
{
"valid": false,
"error": "Token já utilizado"
}3. Redefinir Senha
Endpoint: POST /api/auth/reset-password
interface ResetPasswordRequest {
token: string;
newPassword: string;
}Request:
curl -X POST https://api.tarefaai.com/api/auth/reset-password \
-H "Content-Type: application/json" \
-d '{
"token": "abc123...",
"newPassword": "NovaSenhaSegura456!"
}'Response (200 OK):
{
"success": true,
"message": "Senha redefinida com sucesso"
}Usando a API com Autenticação
Opção 1: Cookies de Sessão (Web)
// Cliente web (fetch com credentials)
const response = await fetch('https://api.tarefaai.com/api/tasks', {
method: 'GET',
credentials: 'include', // Envia cookies automaticamente
headers: {
'Content-Type': 'application/json',
},
});Opção 2: Bearer Token (API/Mobile)
// Cliente API com token
const response = await fetch('https://api.tarefaai.com/api/tasks', {
method: 'GET',
headers: {
'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
'Content-Type': 'application/json',
},
});cURL com Bearer Token:
curl -X GET https://api.tarefaai.com/api/tasks \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json"Verificar Sessão Atual
Endpoint: GET /api/auth/session
Request:
curl -X GET https://api.tarefaai.com/api/auth/session \
-H "Cookie: local-session=123"Response (200 OK):
{
"authenticated": true,
"user": {
"id": 123,
"email": "joao@example.com",
"name": "João Silva",
"role": "USER",
"timezone": "America/Sao_Paulo",
"createdAt": "2025-01-17T10:00:00.000Z"
}
}Response (401 Unauthorized):
{
"authenticated": false
}Autenticação de Admin
Endpoints administrativos requerem role ADMIN. O middleware requireAdmin() valida automaticamente.
Header adicional para admin endpoints:
X-Admin-Key: {admin_secret_key}Exemplo de requisição admin:
curl -X GET https://api.tarefaai.com/api/admin/stats \
-H "Cookie: local-session=123" \
-H "X-Admin-Key: your-admin-secret-key"Erro de permissão:
{
"success": false,
"error": "Unauthorized",
"message": "Admin access required"
}Rate Limiting
Limites por Endpoint
| Endpoint | Limite | Janela |
|---|---|---|
POST /api/auth/login | 5 tentativas | 15 min |
POST /api/auth/register | 3 cadastros | 1 hora |
POST /api/auth/forgot-password | 3 solicitações | 1 hora |
POST /api/auth/reset-password | 5 tentativas | 1 hora |
| Outros endpoints autenticados | 100 requisições | 1 min |
Headers de Rate Limit:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1674820800000Erro de Rate Limit:
{
"success": false,
"error": "Rate limit exceeded",
"message": "Muitas requisições. Tente novamente em 15 minutos.",
"retryAfter": 900
}Códigos de Erro
| Código | Descrição |
|---|---|
| 200 | Sucesso |
| 201 | Recurso criado |
| 400 | Validação falhou |
| 401 | Não autenticado |
| 403 | Sem permissão |
| 409 | Conflito (email já cadastrado) |
| 429 | Rate limit excedido |
| 500 | Erro interno do servidor |
Segurança Best Practices
Para Desenvolvedores
- HTTPS Only: Sempre use HTTPS em produção
- Armazene tokens com segurança: Nunca em localStorage, use cookies httpOnly
- Valide sessões: Sempre verifique a sessão antes de operações sensíveis
- Rotate secrets: Troque secrets regularmente em produção
- Monitor tentativas de login: Implemente alertas para múltiplas falhas
Exemplo de Implementação Segura
// ✅ BOM: Cookie httpOnly com sessão
export async function getSession(): Promise<User | null> {
const cookieStore = await cookies();
const sessionCookie = cookieStore.get('local-session');
if (!sessionCookie?.value) return null;
const userId = parseInt(sessionCookie.value);
const user = await db.query.users.findFirst({
where: eq(users.id, userId),
});
return user || null;
}
// ❌ RUIM: Token em localStorage (vulnerável a XSS)
localStorage.setItem('auth-token', token); // NUNCA FAÇA ISSOPróximos Passos
Referência: Implementação completa em /src/lib/local-auth.ts e /src/app/api/auth/