Saltar a contenido

🔌 Autenticación y Seguridad de la API

La seguridad es un pilar fundamental en el diseño del P2P Dashboard. La API implementa mecanismos robustos de autenticación y autorización para proteger los datos sensibles y asegurar que solo los usuarios y sistemas autorizados puedan interactuar con ella. Se utilizan dos métodos principales de autenticación:

  1. API Keys: Para la autenticación de Workers externos que envían datos a la API de Ingesta.
  2. JSON Web Tokens (JWT): Para la autenticación de usuarios administrativos que acceden a rutas protegidas.

1. Autenticación con API Keys

Las API Keys son cadenas alfanuméricas únicas que se utilizan para identificar y autenticar a los Workers que envían datos al endpoint de ingesta (/api/v1/binance/offers). Cada API Key está asociada a un usuario o sistema específico y puede ser revocada si es necesario.

Generación de API Keys

Las API Keys se generan y gestionan a través de endpoints administrativos protegidos. Un ejemplo de cómo se podría generar una API Key (esto se haría a través de un endpoint administrativo, no directamente por el Worker):

# Ejemplo conceptual de generación de API Key (no es un endpoint real)
import secrets

def generate_api_key():
    prefix = "p2p_ingest_"
    secret = secrets.token_urlsafe(32) # Genera un secreto seguro
    return f"{prefix}{secret}"

# api_key = generate_api_key()
# print(api_key) # Ejemplo: p2p_ingest_AbCdEfGhIjKlMnOpQrStUvWxYz0123456789

Uso de API Keys

Para autenticarse, el Worker debe incluir la API Key en el encabezado X-API-Key de cada solicitud al endpoint de ingesta.

POST /api/v1/binance/offers HTTP/1.1
Host: your-api-domain.com
X-API-Key: p2p_ingest_AbCdEfGhIjKlMnOpQrStUvWxYz0123456789
Content-Type: application/json

[
  // ... cuerpo de la solicitud con datos de ofertas ...
]

Validación de API Keys

En el lado del servidor (FastAPI), la validación de la API Key se realiza mediante una dependencia. Si la API Key no es válida o está ausente, la solicitud será rechazada con un código de estado HTTP 401 Unauthorized.

# p2p_api/dependencies.py (ejemplo conceptual)
from fastapi import Header, HTTPException, Depends
from sqlalchemy.orm import Session
from .crud import get_api_key_by_secret
from .database import get_db

async def get_api_key(x_api_key: str = Header(...), db: Session = Depends(get_db)):
    api_key_record = get_api_key_by_secret(db, api_key_secret=x_api_key)
    if not api_key_record or not api_key_record.is_active:
        raise HTTPException(status_code=401, detail="Invalid API Key")
    return api_key_record

# En un router (ej. p2p_api/routers/binance.py)
# @router.post("/binance/offers")
# async def create_binance_offers(offers: List[OfferCreate], api_key: APIKey = Depends(get_api_key), db: Session = Depends(get_db)):
#     # ... lógica de procesamiento de ofertas ...

2. Autenticación con JSON Web Tokens (JWT)

Los JWT se utilizan para autenticar a los usuarios administrativos que acceden a rutas protegidas (ej. /admin/*). Este método proporciona una forma segura y estándar de gestionar sesiones de usuario.

Flujo de Autenticación JWT

  1. Obtener Token: El usuario envía sus credenciales (nombre de usuario y contraseña) a un endpoint de login (ej. /admin/token).
  2. Generar Token: Si las credenciales son válidas, el servidor genera un JWT que contiene información sobre el usuario (claims) y una firma digital.
  3. Enviar Token: El servidor devuelve el JWT al cliente.
  4. Acceder a Rutas Protegidas: Para acceder a cualquier ruta protegida, el cliente debe incluir el JWT en el encabezado Authorization con el prefijo Bearer.

Endpoint de Login (Ejemplo)

POST /admin/token

  • Descripción: Autentica a un usuario y devuelve un JWT.
  • Cuerpo de la Solicitud (Request Body): OAuth2PasswordRequestForm (username y password).

Ejemplo de Solicitud (Request)

POST /admin/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded

username=admin_user&password=admin_password

Ejemplo de Respuesta (Response)

HTTP/1.1 200 OK
Content-Type: application/json

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer"
}

Uso de JWT para Acceder a Rutas Protegidas

Una vez que el cliente tiene el access_token, debe incluirlo en el encabezado Authorization para todas las solicitudes a rutas protegidas.

GET /admin/monitoring/summary HTTP/1.1
Host: your-api-domain.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Validación de JWT

En el lado del servidor, FastAPI utiliza dependencias para validar el JWT y extraer la información del usuario. Si el token es inválido, ha expirado o está ausente, la solicitud será rechazada.

# p2p_api/dependencies.py (ejemplo conceptual)
from fastapi.security import OAuth2PasswordBearer
from jose import JWTError, jwt
from .config import settings
from .crud import get_user_by_username

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="admin/token")

async def get_current_user(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
    except JWTError:
        raise credentials_exception
    user = get_user_by_username(db, username=username)
    if user is None:
        raise credentials_exception
    return user

# En un router (ej. p2p_api/routers/admin.py)
# @router.get("/monitoring/summary")
# async def get_monitoring_summary(current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
#     # ... lógica para devolver el resumen de monitoreo ...

Consideraciones de Seguridad Adicionales

  • HTTPS: Siempre se debe utilizar HTTPS en producción para cifrar las comunicaciones y proteger las API Keys y los JWT de la interceptación.
  • Rotación de Claves: Implementar una política de rotación regular para las API Keys y los secretos de JWT.
  • Almacenamiento Seguro: Las API Keys y los JWT deben almacenarse de forma segura en el cliente (ej. variables de entorno, gestores de secretos) y nunca en el código fuente.
  • Validación de Entrada: Continuar con la validación estricta de todas las entradas para prevenir ataques comunes como la inyección SQL o XSS.
  • Manejo de Errores: Evitar exponer información sensible en los mensajes de error de la API.

La implementación de estos mecanismos de autenticación y seguridad es vital para proteger la integridad y confidencialidad de los datos en el P2P Dashboard.