Как подружить Django и Nuxt Auth

Задача: подружить фреймворк Django и модуль авторизации Nuxt: nuxt/auth. При этом очень важно "на затыкать" и не отключать алгоритм CSRF защиты Django.

Рассмотрим необходимую нам последовательность запросов:

  1. Отправить запрос для получения CSRF токена
  2. Сервер в результате вернёт куку (cookie) с токеном
  3. С использованием этого токена отправить авторизационные данные (логин/пароль)
  4. Получить в ответ куку с токеном сессии.
  5. Использовать её для всех дальнейших запросов

Некоторая сложность тут заключается в том, что Django ожидает CSRF токен с заголовком X-CSRFToken, а nuxt/auth ожидает куку с хедером XSRF-TOKEN.

Конфигурация Django

Для начала сообщим фреймфорку:

  1. В каком виде отдавать CSRF токен
  2. От каких адресов могут прилетать запросы
  3. Разрешим принимать заголовок x-xsrf-token (его нам будет отдавать nuxt/auth)
Развернуть
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOWED_ORIGINS = ["allowed ip address"]
CSRF_COOKIE_NAME = "XSRF-TOKEN"

CORS_ALLOW_HEADERS = list(default_headers) + [
    "x-xsrf-token",
]

Методы для авторизации

Добавим необходимые для авторизации/логаута/получения данных о пользователе вьюшки.

Установка CSRF токена:

Развернуть
@ensure_csrf_cookie
def auth_set_csrf_cookie(request):
    return JsonResponse({"details": "CSRF cookie set"})

Авторизация:

Развернуть
@require_POST
def auth_login(request):
    data = json.loads(request.body)
    username = data.get("username")
    password = data.get("password")
    # добавить необходимые проверки
    user = authenticate(username=username, password=password)
    if user is not None:
        login(request, user)
        return JsonResponse({"detail": "Success"})
    return JsonResponse({"detail": "Invalid credentials"}, status=400)

Выход из системы:

Развернуть
@require_POST
def auth_logout(request):
    logout(request)
    return JsonResponse({"detail": "Logout Successful"})

Последний шаг — настройка URL схемы:

Развернуть
from django.urls import path

from . import views

urlpatterns = [
    path("auth/csrf/", views.auth_set_csrf_cookie),
    path("auth/login/", views.auth_login),
    path("auth/logout/", views.auth_logout)
]

Далее переходим к настройке нашего Nuxt приложения.

Настройка nuxt/auth

Для начала сконфигурируем модуль nuxt/auth... (nuxt.config.js)

Развернуть
auth: {
  strategies: {
    cookie: {
      user: {
        property: false,
        autoFetch: true
      },
      endpoints: {
        login: {
          url: '/api/auth/login/',
          method: 'post',
          propertyName: false
        },
        logout: {
          url: '/api/auth/logout/',
          method: 'post',
          propertyName: false
        },
        csrf: {
          url: '/api/auth/csrf'
        }
      },
      tokenRequired: false,
      tokenType: false
    }
  }
}
...
router: {
  middleware: ['auth']
}

Мы сообщили модулю nuxt/auth как получить CSRF токен, как проводить авторизацию и выход из системы. Теперь нужно добавить настройку библиотеки axios (наиболее часто используемая в рамках Nuxt библиотека для сетевых запросов), чтобы при каждом запросе к серверу прикладывались авторизационные данные:

Развернуть
axios: {
    credentials: true,
    baseURL: 'django server address'
}

Собственно, на этом конфигурация Django и nuxt/auth закончена. Теперь Django знает как отдавать CSRF токен, а nuxt/auth знает как проводить процедуру авторизации. Последний шаг — пример как использовать модуль nuxt/auth:

Развернуть
login() {
  this.$auth.loginWith('cookie', {
    data: {
      username: 'login...',
      password: 'password...'
    }
  })
    .then(() => this.$toast.success('Добро пожаловать'))
    .catch((e) => this.$toast.error(e.response.data.detail));
}

На этом у меня всё. Если хотите автоматических редиректов при логине/логауте, нужно заполнить поле redirect в конфигурации модуля auth в файле nuxt.config.js.

Теперь точно всё, всем успехов!