Autenticação

api
backend
autenticação
segurança

Sistema de autenticação JWT baseado em sessões com suporte a OAuth e recuperação de senha

Nesta Página

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 httpOnly e secure (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=604800

Para 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=0

Recuperaçã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:

  1. Sistema gera token único de 64 caracteres
  2. Token válido por 1 hora
  3. 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

EndpointLimiteJanela
POST /api/auth/login5 tentativas15 min
POST /api/auth/register3 cadastros1 hora
POST /api/auth/forgot-password3 solicitações1 hora
POST /api/auth/reset-password5 tentativas1 hora
Outros endpoints autenticados100 requisições1 min

Headers de Rate Limit:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1674820800000

Erro 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ódigoDescrição
200Sucesso
201Recurso criado
400Validação falhou
401Não autenticado
403Sem permissão
409Conflito (email já cadastrado)
429Rate limit excedido
500Erro interno do servidor

Segurança Best Practices

Para Desenvolvedores

  1. HTTPS Only: Sempre use HTTPS em produção
  2. Armazene tokens com segurança: Nunca em localStorage, use cookies httpOnly
  3. Valide sessões: Sempre verifique a sessão antes de operações sensíveis
  4. Rotate secrets: Troque secrets regularmente em produção
  5. 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 ISSO

Próximos Passos


Referência: Implementação completa em /src/lib/local-auth.ts e /src/app/api/auth/