🔌 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:
- API Keys: Para la autenticación de Workers externos que envían datos a la API de Ingesta.
- 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
- Obtener Token: El usuario envía sus credenciales (nombre de usuario y contraseña) a un endpoint de login (ej.
/admin/token). - 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.
- Enviar Token: El servidor devuelve el JWT al cliente.
- Acceder a Rutas Protegidas: Para acceder a cualquier ruta protegida, el cliente debe incluir el JWT en el encabezado
Authorizationcon el prefijoBearer.
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.