Secure Swagger & ReDoc in Django REST Framework with DRF Spectacular: Best Practices for API Security
API documentation tools like Swagger UI and ReDoc make development easier, but they also expose every endpoint, schema, and request structure to anyone who can access the URL.
If you deploy your Django REST Framework project without protecting /api/docs/ or /api/schema/, you're unintentionally giving outsiders:
- A complete map of all your APIs
- All request/response structures
- Authentication patterns
- Internal admin/debug endpoints
This makes exploitation easier and increases your attack surface.
That’s why Swagger must never be public in production. In this guide, we’ll show a clean, secure way to protect your API documentation using DRF Spectacular in a Django REST Framework project.

A secure architecture for safeguarding Swagger and ReDoc in DRF using DRF Spectacular.
# Directory structure
core/
docs/
swagger_view.py
urls.py
settings.py
core/docs/swagger_view.py
from django.shortcuts import redirect
from drf_spectacular.views import (
SpectacularAPIView,
SpectacularSwaggerView,
SpectacularRedocView,
)
class AdminOnlyMixin:
"""
Restrict access to authenticated superusers.
"""
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return redirect(f"/admin/login/?next={request.path}")
if not request.user.is_superuser:
return redirect("/403/") # Make sure a 403 page exists
return super().dispatch(request, *args, **kwargs)
class SuperuserSchemaView(AdminOnlyMixin, SpectacularAPIView):
pass
class SuperuserSwaggerView(AdminOnlyMixin, SpectacularSwaggerView):
pass
class SuperuserRedocView(AdminOnlyMixin, SpectacularRedocView):
pass
core/urls.y
from django.urls import path
from core.docs import (
SuperuserRedocView,
SuperuserSchemaView,
SuperuserSwaggerView,
)
urlpatterns = [
# API documentation (protected)
path("api/schema/", SuperuserSchemaView.as_view(), name="schema"),
path("api/docs/", SuperuserSwaggerView.as_view(url_name="schema"), name="swagger-ui"),
path("api/redoc/", SuperuserRedocView.as_view(url_name="schema"), name="redoc"),
]
core/settings.py
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
# JWT for external API clients
"rest_framework_simplejwt.authentication.JWTAuthentication",
# Session auth so Swagger works automatically after admin login
"rest_framework.authentication.SessionAuthentication",
),
"DEFAULT_PERMISSION_CLASSES": (
"rest_framework.permissions.IsAuthenticated",
),
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
}
SPECTACULAR_SETTINGS = {
"TITLE": "Your API",
"DESCRIPTION": "API documentation",
"VERSION": "1.0.0",
# Allow our custom view to control permissions manually
"SERVE_PERMISSIONS": ["rest_framework.permissions.IsAdminUser"],
# Use DRF’s normal authentication classes (Session + JWT)
"SERVE_AUTHENTICATION": None,
# Important: Do NOT expose schema automatically in unrestricted mode
"SERVE_INCLUDE_SCHEMA": False,
}
Notes:
- SessionAuthentication allows admin users to access protected docs easily.
- SERVE_INCLUDE_SCHEMA = False ensures your schema isn’t automatically exposed.
And that’s the real value of securing your API documentation: you empower your team without empowering your attackers. When Swagger and ReDoc live behind proper authentication, your developers gain clarity, your system gains integrity, and your attack surface quietly shrinks. Secure the docs, protect the blueprint, and let your API evolve with confidence — exactly the way production-grade engineering should be. Appreciate your time. Until next time 👋.
Top comments (0)