🐛 Типичные ошибки: Auth/DRF

⚡ Топ-5 ошибок

  1. Не добавить rest_framework.authtoken в INSTALLED_APPS и/или не сделать migrate
  2. Написать Token вместо Bearer в заголовке JWT (или наоборот)
  3. Настроить auth глобально в settings.py, но не переопределить для конкретных представлений
  4. Не установить djangorestframework-simplejwt перед настройкой JWTAuthentication
  5. Не добавить маршруты получения токена (obtain_auth_token / TokenObtainPairView) в urls.py

Ошибка 1: Забыли migrate для TokenAuthentication

Симптом: ProgrammingError: relation "authtoken_token" does not exist

Неверно

INSTALLED_APPS = [
    'rest_framework.authtoken',
]
# Забыли выполнить:
# python manage.py migrate

Верно

INSTALLED_APPS = [
    'rest_framework.authtoken',
]
# Обязательно выполнить:
# python manage.py migrate
# Проверить: таблица authtoken_token создана

Почему: rest_framework.authtoken добавляет Django-модель Token. Как и любая другая модель, она требует миграции для создания таблицы в БД.

Ошибка 2: Неправильный формат заголовка Authorization

Симптом: HTTP 401 при правильном токене

Неверно

# Для TokenAuthentication
Authorization: Bearer 9944b0...   # НЕВЕРНО!
Authorization: Basic 9944b0...    # НЕВЕРНО!

# Для JWTAuthentication
Authorization: Token eyJhbGci...  # НЕВЕРНО!
Authorization: Basic eyJhbGci... # НЕВЕРНО!

Верно

# Для TokenAuthentication
Authorization: Token 9944b0...    # ВЕРНО

# Для JWTAuthentication
Authorization: Bearer eyJhbGci... # ВЕРНО

# Для BasicAuthentication
Authorization: Basic dXNlcm5...   # ВЕРНО

Почему: Каждый механизм аутентификации ожидает своё ключевое слово в заголовке. DRF проверяет именно это слово, чтобы понять, какой класс должен обрабатывать запрос.

Ошибка 3: Конфликт глобальных и поуровневых настроек

Симптом: Аутентификация работает не так, как ожидалось

Путаница

# settings.py — глобально JWT
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
}

# views.py — но забыли переопределить для публичных
class CategoryViewSet(viewsets.ModelViewSet):
    queryset = Category.objects.all()
    # Нет permission_classes -> используется глобальный IsAuthenticated
    # Доступ закрыт для анонимов, хотя хотели открытый!

Верно

# views.py — явно задаём для публичных представлений
from rest_framework.permissions import AllowAny

class CategoryViewSet(viewsets.ModelViewSet):
    queryset = Category.objects.all()
    permission_classes = [AllowAny]  # Явно открытый

# Или задаём глобальный AllowAny и закрываем только нужные
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.AllowAny',
    ],
}

Ошибка 4: Пакет не установлен

Симптом: ModuleNotFoundError: No module named 'rest_framework_simplejwt'
# Неверно: сразу добавить в settings.py без установки
INSTALLED_APPS = ['rest_framework_simplejwt']  # ModuleNotFoundError!

# Верно: сначала установить
pip install djangorestframework-simplejwt
# Затем добавить в settings.py

Ошибка 5: Нет маршрута для получения токена

Симптом: 404 Not Found при попытке получить токен
# Неверно: настроили TokenAuthentication, но нет маршрута
# пользователь пытается POST /api-token-auth/ -> 404

# Верно: явно добавить маршрут в urls.py
from rest_framework.authtoken.views import obtain_auth_token
urlpatterns = [
    path('api-token-auth/', obtain_auth_token, name='api_token_auth'),
]

Почему: DRF не добавляет маршруты автоматически. obtain_auth_token — это обычное представление, которое нужно явно зарегистрировать в urlpatterns.

Ошибка 6: access-токен JWT истёк, не используют refresh

Симптом: HTTP 401 {"detail": "Given token not valid for any token type", "code": "token_not_valid"} через 5 минут после получения токена
# Неверно: пытаться использовать истёкший access-токен

# Верно: обновить access-токен через refresh
# POST http://127.0.0.1:8000/api/token/refresh/
# Body: {"refresh": "eyJhbGci...refresh_token..."}
# Ответ: {"access": "eyJhbGci...новый_access..."}

# Убедиться, что маршрут зарегистрирован:
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh')

Ошибка 7: BasicAuthentication без HTTPS в production

Симптом: Утечка учётных данных пользователей
# Проблема: Base64 — не шифрование
import base64
base64.b64decode("dXNlcm5hbWU6cGFzc3dvcmQ=")
# => b'username:password'  — тривиально раскодируется!

# Правило: BasicAuthentication только с HTTPS в production
# Для development/тестирования — допустимо
# Для production — только поверх TLS/SSL
← К оглавлению урока    Ресурсы →