Saltar a contenido

Autenticación

La API tiene un sistema de autenticación multi-nivel.

Diagrama de autenticación

flowchart TD
    REQ["Request entrante"] --> ROUTE{"¿Qué tipo<br/>de ruta?"}

    ROUTE -->|"Admin only<br/>(api-keys, admin/*)"| ADMIN_CHECK
    ROUTE -->|"Cliente<br/>(stores, orders, etc)"| CLIENT_CHECK
    ROUTE -->|"Webhook"| SIG_CHECK
    ROUTE -->|"Pública<br/>(login, callback, validate)"| PUBLIC["✅ Sin auth"]

    subgraph ADMIN["adminToken()"]
        ADMIN_CHECK{"¿x-api-token<br/>== API_TOKEN?"} -->|No| ADMIN_REJECT["❌ 403"]
        ADMIN_CHECK -->|Sí| ADMIN_OK["✅ Acceso admin<br/>Inyecta db"]
    end

    subgraph CLIENT["clientToken()"]
        CLIENT_CHECK{"¿Tiene<br/>x-api-token?"} -->|No| CLIENT_401["❌ 401"]
        CLIENT_CHECK -->|Sí| IS_ADMIN{"¿Es el<br/>Admin Token?"}
        IS_ADMIN -->|Sí| HAS_CLIENT{"¿Tiene ?client=<br/>en query?"}
        HAS_CLIENT -->|No| CLIENT_400["❌ 400 Admin<br/>requires client"]
        HAS_CLIENT -->|Sí| CLIENT_ADMIN["✅ clientName = query.client"]
        IS_ADMIN -->|No| DB_CHECK["Buscar en api_keys"]
        DB_CHECK --> EXISTS{"¿Existe y<br/>está activa?"}
        EXISTS -->|No| CLIENT_403["❌ 403"]
        EXISTS -->|Sí| CLIENT_OK["✅ clientName = apiKey.clientName"]
    end

    subgraph WEBHOOK["webhookSignature()"]
        SIG_CHECK["Validar HMAC-SHA256<br/>x-signature header"] -->|Inválida| SIG_REJECT["❌ 401"]
        SIG_CHECK -->|Válida| SIG_OK["✅ Procesar webhook"]
    end

    style ADMIN_OK fill:#00d4aa,color:#000
    style CLIENT_ADMIN fill:#00d4aa,color:#000
    style CLIENT_OK fill:#00d4aa,color:#000
    style SIG_OK fill:#00d4aa,color:#000
    style PUBLIC fill:#00d4aa,color:#000
    style ADMIN_REJECT fill:#ff4d6a,color:#000
    style CLIENT_401 fill:#ff4d6a,color:#000
    style CLIENT_400 fill:#ff4d6a,color:#000
    style CLIENT_403 fill:#ff4d6a,color:#000
    style SIG_REJECT fill:#ff4d6a,color:#000

Niveles de acceso

Admin Token

Token global definido en la variable de entorno API_TOKEN. Se usa en dos contextos:

En rutas admin-only (/api-keys, /admin/*): acceso directo, no requiere parámetros extra.

# Listar API keys — solo necesita el admin token
curl https://api.example.com/api-keys \
  -H "x-api-token: MI_ADMIN_TOKEN"

En rutas de cliente (/stores, /orders, etc.): requiere ?client= para indicar en nombre de qué cliente opera.

# Operar como un cliente desde el admin token
curl https://api.example.com/stores?client=mi-cliente \
  -H "x-api-token: MI_ADMIN_TOKEN"

Permiso
Crear/revocar API keys
Ver info de cualquier cliente
Simular eventos de órdenes
Ver activity logs y webhook logs
Operar como cualquier cliente (con ?client=)

Client API Key

Key generada por el admin para cada cliente. Prefijo mk_, 64 caracteres hexadecimales.

El middleware identifica al cliente automáticamente por su key, no necesita enviar ?client= en ninguna request.

curl https://api.example.com/stores \
  -H "x-api-token: mk_a1b2c3d4e5f6..."

Permiso
Gestionar sus stores/POS
Crear/consultar órdenes
Ver estado OAuth propio
Ver datos de otros clientes
Gestionar API keys
Endpoints de admin

Webhook Signature

Los webhooks de MercadoPago se validan con HMAC-SHA256. No usan API key ni admin token.

x-signature: ts=1234567890,v1=abc123def456...

La validación construye un manifest con el formato:

id:{data.id};request-id:{x-request-id};ts:{timestamp};

Y verifica:

  1. Hash HMAC-SHA256 del manifest contra el WEBHOOK_SECRET
  2. Tolerancia de timestamp (5 minutos máximo)
  3. Comparación timing-safe para evitar timing attacks

Middlewares

adminToken()

Usado en rutas admin-only: /api-keys, /admin/*.

Solo acepta el admin token. Rechaza client keys.

// Inyecta en el context:
c.get('db') // Database — instancia de Drizzle

clientToken()

Usado en rutas de cliente: /stores, /orders, /terminals, /oauth/status, etc.

Acepta tanto admin token (con ?client=) como client API key.

// Inyecta en el context:
c.get('clientName') // string — nombre del cliente
c.get('db')         // Database — instancia de Drizzle

webhookSignature()

Usado solo en POST /webhooks. Valida la firma HMAC-SHA256 de MercadoPago.

Validación de API Key

Endpoint público GET /oauth/validate para verificar si una key es válida sin pasar por ningún middleware de auth:

curl https://api.example.com/oauth/validate \
  -H "x-api-token: mk_mi_key_aqui"

    { "valid": true, "type": "client", "client": "mi-cliente" }
    { "valid": true, "type": "admin", "client": null }
    { "error": "Invalid API key" }