-
Notifications
You must be signed in to change notification settings - Fork 12
Description
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:
- Frontend solicita un challenge →
GET /auth - Backend genera una transacción Stellar como challenge y la firma con su server key
- Frontend la firma con la wallet del usuario →
POST /auth - Backend verifica ambas firmas → emite un JWT con la wallet address del usuario
- 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 /investments→WHERE investorAddress = walletFromJWTGET /loans→ restringido solo al rol backofficeGET /campaigns→ sin filtro (público)
Relación con otros issues
- feat(security): implementar autenticación por API Key en core #49 — API Key guard (service-to-service). Este issue lo extiende con auth a nivel de usuario.
- investor: invest in campaign #10, investor: claim roi #11 — Features de frontend de investor que consumirán endpoints de DB. Debería resolverse antes o en paralelo.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status