Skip to content

feat(security): autorización a nivel de usuario para endpoints de base de datos #68

@CoKeFish

Description

@CoKeFish

Descripción

El issue #49 introduce autenticación por API Key para comunicación service-to-service entre los
frontends y core. Esto protege contra acceso externo, pero no resuelve la autorización a nivel
de usuario
para los endpoints de base de datos.

Actualmente los endpoints de DB (campaigns, investments, loans) no tienen control de acceso
por usuario. Cualquier usuario de la aplicación podría leer datos de otros usuarios manipulando
requests desde el browser (devtools, proxy, curl contra las API routes de Next.js).


Contexto

Qué protege la API Key y qué no

La API Key del issue #49 autentica la aplicación (backoffice o investors), no al usuario.
Ambas apps pasan el guard, pero requieren niveles de acceso distintos. Además, un usuario del
frontend puede modificar el JavaScript, interceptar requests o llamar directamente a las API
routes de Next.js con parámetros arbitrarios.

Endpoints de base de datos expuestos

Endpoint Datos Riesgo
GET /investments Todas las inversiones de todos los inversores Un inversor podría ver inversiones de otros
GET /loans Todos los préstamos, incluyendo receiver Expone identidad del prestatario a inversores. Viola la regla: "No borrower PII exposed to investors"
PATCH /loans/:id Actualizar cualquier préstamo La app de investors no debería tener acceso de escritura a loans
DELETE /loans/:id Eliminar cualquier préstamo Mismo caso
GET /campaigns Todas las campañas Información pública, sin riesgo

Estado actual

Ningún frontend consume estos endpoints de DB todavía. El riesgo se materializa cuando se
implementen los issues #10 (invest in campaign) y #11 (claim ROI), que necesitarán consumir datos
de campaigns e investments.

Por qué SEP-10 y no un auth provider externo

Los usuarios ya tienen wallet de Stellar. SEP-10 (Stellar Web Authentication) es el estándar
oficial para autenticación web mediante firmas de wallet. No requiere proveedores externos
(Auth0, Supabase Auth, etc.), no necesita passwords, y produce un JWT que el backend puede usar
para identificar al usuario.

Referencia: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0010.md


Solución propuesta

1. Autenticación de usuario via SEP-10

Implementar el flujo challenge-response de SEP-10 en apps/core:

  1. Frontend solicita un challenge → GET /auth
  2. Backend genera una transacción Stellar como challenge y la firma con su server key
  3. Frontend la firma con la wallet del usuario → POST /auth
  4. Backend verifica ambas firmas → emite un JWT con la wallet address del usuario
  5. El JWT se envía en los requests subsiguientes — el backend sabe quién es el usuario

usuario ──[conecta wallet]──► frontend ──[GET /auth]──► core (genera challenge)
frontend ◄──[challenge tx]── core
usuario ──[firma con wallet]──► frontend ──[POST /auth + signed tx]──► core (verifica)
frontend ◄──[JWT]── core
frontend ──[x-api-key + Authorization: Bearer JWT]──► core ──► Controller

Este JWT se usaría junto con la API Key del issue #49:

  • API Key → autentica la aplicación (service-to-service)
  • SEP-10 JWT → autentica al usuario (identidad basada en wallet)

2. RBAC por identidad de API Key

El ApiKeyGuard del issue #49 ya sabe qué key se usó. Exponer esto como un rol (backoffice |
investor) y restringir endpoints por rol:

  • Endpoints de loans (CRUD) → solo backoffice
  • Endpoints de investments (lectura) → ambos, pero filtrado por usuario en investor
  • Endpoints de campaigns → públicos

Implementar con un decorador @Roles('backoffice') y un RolesGuard que lea el rol desde el
request.

3. Filtrado de datos por wallet address del JWT

Para endpoints consumidos por la app de investors, filtrar resultados por la wallet del usuario
autenticado:

  • GET /investmentsWHERE investorAddress = walletFromJWT
  • GET /loans → restringido solo al rol backoffice
  • GET /campaigns → sin filtro (público)

Relación con otros issues


Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions