Hoy vamos a aprender cómo podemos añadir una contraseña de acceso a Swagger en FastAPI. De esta forma securizaremos en dashboard de Swagger y el json de definiciones.
Lo primero que haremos es ir al main.py de FastAPI.
Vamos a crear un Middleware que nos permitirá interceptar las llamadas al endpoint /openapi.json y /docs y solicitaremos un usuario y contraseña en esos endpoints.
import os from dotenv import load_dotenv from fastapi import FastAPI, Depends, HTTPException, status from fastapi.security import HTTPBasic, HTTPBasicCredentials from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse from starlette.middleware.base import BaseHTTPMiddleware import base64 load_dotenv() # Configuración de la autenticación básica security = HTTPBasic() valid_username = os.getenv("SWAGGER_USER") valid_password = os.getenv("SWAGGER_PASSWORD") def authenticate(credentials: HTTPBasicCredentials = Depends()): if credentials.username != valid_username or credentials.password != valid_password: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect username or password", headers={"WWW-Authenticate": "Basic"}, ) # Middleware para autenticar las rutas de documentación class AuthDocsMiddleware(BaseHTTPMiddleware): async def dispatch(self, request, call_next): # Verificamos si es una solicitud a /docs o /openapi.json (y cualquier otra ruta que contenga "openapi.json") if "/openapi.json" in request.url.path or "/docs" in request.url.path: auth_header = request.headers.get("Authorization") if not auth_header or not auth_header.startswith("Basic "): # Si no hay encabezado Authorization, respondemos con 401 y el encabezado WWW-Authenticate return JSONResponse( status_code=status.HTTP_401_UNAUTHORIZED, content={"detail": "Missing or invalid authorization header"}, headers={"WWW-Authenticate": "Basic"}, ) # Extraemos y decodificamos las credenciales try: base64_credentials = auth_header[6:] # Eliminamos el prefijo "Basic " decoded_credentials = base64.b64decode(base64_credentials).decode("utf-8") username, password = decoded_credentials.split(":", 1) # Creamos el objeto de credenciales credentials = HTTPBasicCredentials(username=username, password=password) # Ejecutamos la función de autenticación authenticate(credentials) except Exception as e: return JSONResponse( status_code=status.HTTP_401_UNAUTHORIZED, content={"detail": "Incorrect username or password"}, headers={"WWW-Authenticate": "Basic"}, ) return await call_next(request) # Agregamos el middleware app.add_middleware(AuthDocsMiddleware)
Ahora crearemos un archivo .env con los credenciales necesarios:
.env
SWAGGER_USER="admin" SWAGGER_PASS="admin123"
Y cuándo accedamos al Swagger /docs nos pedirá autenticación:
Ingeniero en Informática, Investigador, me encanta crear cosas o arreglarlas y darles una nueva vida. Escritor y poeta. Más de 20 APPs publicadas y un libro en Amazon.