FastAPI: Seguridad
Aprende a proteger APIs con FastAPI usando autenticación OAuth2, tokens JWT, hash de contraseñas y validación robusta de datos.
Aprende FastAPI GRATIS y certifícateSeguridad en FastAPI
La seguridad en aplicaciones web es un aspecto fundamental que no puede pasarse por alto. FastAPI proporciona herramientas integradas que simplifican la implementación de medidas de seguridad robustas, permitiendo proteger nuestras APIs de manera eficiente y siguiendo estándares de la industria.
Fundamentos de seguridad en APIs
Las APIs REST están expuestas a múltiples amenazas de seguridad. Los ataques más comunes incluyen acceso no autorizado, inyección de código malicioso y exposición de datos sensibles. FastAPI aborda estos problemas mediante un sistema de autenticación y autorización bien estructurado.
La autenticación verifica la identidad del usuario, mientras que la autorización determina qué recursos puede acceder ese usuario autenticado. FastAPI integra ambos conceptos de forma transparente, utilizando estándares como OAuth2 y JWT (JSON Web Tokens).
Tokens de acceso y JWT
Los tokens JWT son el mecanismo más utilizado para mantener sesiones seguras en APIs modernas. Un token JWT contiene información codificada sobre el usuario y tiene una fecha de expiración que limita su validez temporal.
from datetime import datetime, timedelta
from jose import JWTError, jwt
from passlib.context import CryptContext
# Configuración de seguridad
SECRET_KEY = "tu-clave-secreta-muy-segura"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def create_access_token(data: dict):
to_encode = data.copy()
expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
Este ejemplo muestra cómo generar un token de acceso con una duración limitada. La biblioteca jose
maneja la codificación JWT, mientras que passlib
se encarga del hash de contraseñas de forma segura.
Autenticación con OAuth2
FastAPI implementa OAuth2 de manera nativa, proporcionando un flujo de autenticación estándar. El esquema OAuth2 con contraseña es el más común para APIs internas.
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
app = FastAPI()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
def verify_token(token: str = Depends(oauth2_scheme)):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Token inválido"
)
return username
except JWTError:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Token inválido"
)
El OAuth2PasswordBearer extrae automáticamente el token del header Authorization
. La función verify_token
valida el token y extrae la información del usuario, lanzando excepciones HTTP apropiadas si el token es inválido.
Protección de endpoints
Una vez configurada la autenticación, podemos proteger endpoints específicos utilizando el sistema de dependencias de FastAPI.
from fastapi import Depends
@app.get("/usuarios/perfil")
async def obtener_perfil(usuario_actual: str = Depends(verify_token)):
return {"usuario": usuario_actual, "mensaje": "Perfil del usuario"}
@app.get("/admin/usuarios")
async def listar_usuarios(usuario_actual: str = Depends(verify_token)):
# Aquí podrías verificar si el usuario tiene permisos de administrador
return {"usuarios": ["usuario1", "usuario2"]}
Los endpoints protegidos requieren un token válido para ser accedidos. FastAPI maneja automáticamente la validación y devuelve errores HTTP 401 si la autenticación falla.
Hash de contraseñas
El almacenamiento seguro de contraseñas es crucial. Nunca debemos guardar contraseñas en texto plano. FastAPI recomienda usar passlib
con el algoritmo bcrypt.
def hash_password(password: str):
return pwd_context.hash(password)
def verify_password(plain_password: str, hashed_password: str):
return pwd_context.verify(plain_password, hashed_password)
# Ejemplo de uso en registro de usuario
@app.post("/registro")
async def registrar_usuario(username: str, password: str):
hashed_password = hash_password(password)
# Guardar usuario con contraseña hasheada en base de datos
return {"mensaje": "Usuario registrado correctamente"}
El hashing es un proceso unidireccional que convierte la contraseña original en una cadena irreversible. La función verify_password
compara la contraseña ingresada con el hash almacenado sin necesidad de descifrar.
Middleware de seguridad
FastAPI permite implementar middleware personalizado para añadir capas adicionales de seguridad, como limitación de velocidad o validación de headers.
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.trustedhost import TrustedHostMiddleware
# Configuración CORS para controlar acceso desde navegadores
app.add_middleware(
CORSMiddleware,
allow_origins=["https://mi-frontend.com"],
allow_credentials=True,
allow_methods=["GET", "POST"],
allow_headers=["*"],
)
# Validación de hosts confiables
app.add_middleware(
TrustedHostMiddleware,
allowed_hosts=["mi-api.com", "*.mi-api.com"]
)
El middleware CORS controla qué dominios pueden acceder a nuestra API desde navegadores web. El TrustedHostMiddleware previene ataques de Host Header Injection validando el header Host de las peticiones.
Validación de datos de entrada
La validación robusta de datos de entrada previene inyecciones y otros ataques. FastAPI utiliza Pydantic para validar automáticamente los datos recibidos.
from pydantic import BaseModel, validator
import re
class UsuarioRegistro(BaseModel):
username: str
email: str
password: str
@validator('username')
def validar_username(cls, v):
if not re.match("^[a-zA-Z0-9_]+$", v):
raise ValueError('Username solo puede contener letras, números y guiones bajos')
return v
@validator('password')
def validar_password(cls, v):
if len(v) < 8:
raise ValueError('La contraseña debe tener al menos 8 caracteres')
return v
Los validadores personalizados de Pydantic permiten implementar reglas de negocio específicas y prevenir la entrada de datos maliciosos o mal formateados.
Lecciones de este módulo de FastAPI
Lecciones de programación del módulo Seguridad del curso de FastAPI.