AG & Dev

Настройка аутентификации в Keystatic CMS (Local mode) в проекте Next.js

5 мая 2026 г.

Другие статьи

Dockerfile для Keystone CMS 6
Dockerfile и compose.yaml для развёртывания Keystone CMS 6
Валидация и обработка формы на сервере
Валидация и обработка формы на сервере при помощи React-хука useActionState
Глобальное состояние в React
Глобальное состояние в React без подключения сторонних библиотек
Яндекс Карты в проекте Next.js
Подключение Яндекс Карты (API 3) к проекту Next.js (App Router)
Подключение к Headless CMS из Next.js
Пример подключения к Headless CMS (Wordpress) из приложения Next.js посредством REST API
Устранение FOUC в Next.js
Устранение FOUC-эффекта при использовании тёмной темы сайта в Next.js
Подключение Payload CMS к проекту Next.js
Как подключить Payload CMS к существующему проекту Next.js
Создание своего Rehype-плагина
Создание Rehype-плагина для корректировки HTML-кода при конвертировании из Markdown
Яндекс Метрика в проекте SvelteKit
Подключение счётчика Яндекс Метрики к проекту на SvelteKit (Svelte 5)
Анимация псевдоэлемента при помощи Anime.js
Анимация псевдоэлемента при помощи JavaScript-библиотеки Anime.js
Деплой сайта на хостинг через SFTP
Развёртывание сайта на хостинге в один клик
Липкий элемент с возможностью скроллинга
Скроллинг «липкого» элемента, превышающего высоту экрана, с помощью Svelte
Все статьи

Технологический стек

AG & Dev

Разработка быстрых и надёжных веб-сайтов на базе самых современных технологий

Профиль на GitHub

Инструменты

React
Next.js
Tailwind

Платформы

Node.js
Docker
Nginx

CMS

Directus
Keystone
Keystatic

Довольно часто, при создании лендинга или небольшого сайта, заказчик просит предоставить ему возможность самостоятельного редактирования информации на лендинге/сайте. Нет никаких проблем в том, чтобы прикрутить к сайту какую-нибудь CMS. Но тут начинается самое интересное – устанавливать CMS, вроде Strapi, Directus, Payload и т.п., которые используют для своей работы базу данных, для лендинга или небольшого сайта – это как «из пушки во воробьям стрелять».

База данных нужна там, где необходим поиск, сортировка, выборка и др. функционал, требующий быстрой обработки больших объёмов информации. Кроме того, база данных требует выполнения сложных миграций при изменении структуры сайта и тянет за собой увеличение расходов на поддержку, обслуживание, резервное копирование, защиту от несанкционированного доступа или взлома. И всё это ради лендинга или небольшого сайта?!

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

К счастью, для таких кейсов есть готовые решения – CMS, не использующие для своей работы базу данных, а сохраняющие данные в файлах специальных форматов – Markdown, YAML, JSON и т.п. Но и тут не всё просто.

Долгое время я пытался найти подходящую CMS, которая соответствует следующим требованиям:

  1. Не использует базу данных.
  2. Не зависит от сторонних сервисов и может работать автономно на хостинге заказчика.
  3. Не требует пересборки сайта после внесения изменений и позволяет обновлять сайт в режиме реального времени.

Не могу утверждать, что я перебрал все актуальные CMS, но попыток было много, и все испытанные мною CMS, соответствовали только двум из трёх, перечисленных выше, требований. Даже самые близкие к моим требованиям Decap CMS и Pages CMS не умеют работать полностью автономно и требуют для своей работы интеграцию с GitHub.

Единственная CMS, которая соответствует всем трём перечисленным требованиям – это Keystatic CMS, которая может работать в двух режимах – «Github mode» и «Local mode». «Github mode» требует интеграцию с CitHub, а вот «Local mode» как раз умеет работать полностью автономно.

К сожалению, Keystatic CMS в режиме «Local mode» пока не имеет встроенной аутентификации. Это означает, что аутентификацию (вход) в CMS необходимо реализовать самостоятельно. А если мы используем CMS без базы данных и без зависимостей от сторонних сервисов, то логично, чтобы и механизм аутентификации не использовал базу данных и не зависел от сторонних сервисов, иначе какой во всём этом смысл?

Найти библиотеку аутентификации, умеющую работать без базы данных и без зависимостей от сторонних сервисов, оказалось гораздо проще, чем найти саму CMS. Выбор пал на популярную библиотеку Auth.js потому, что она легко интегрируется с Next.js.

Настройка

1. Устанавливаем библиотеку next-auth (актуальная версия – 5 beta 31):

terminal
npm i next-auth@5.0.0-beta.31

2. Создаём файл proxy.js в корне проекта или в папке src (если она есть):

proxy.js
export { auth as proxy } from "@/lib/auth";
 
export const config = {
  matcher: "/keystatic/:path*",
};

3. Создаём файл route.js в папке app/api/auth/[...nextauth]:

app/api/auth/[...nextauth]/route.js
import { handlers } from "@/lib/auth";
export const { GET, POST } = handlers;

4. Создаём файл auth.js в папке lib:

lib/auth.js
import NextAuth from "next-auth";
import Credentials from "next-auth/providers/credentials";
 
import { users } from "@/data/users";
 
const credentials = {
  email: {
    type: "email",
    label: "Логин",
  },
  password: {
    type: "password",
    label: "Пароль",
  },
};
 
export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [
    Credentials({
      credentials: credentials,
 
      authorize: (credentials) => {
        return getUser(credentials);
      },
    }),
  ],
 
  callbacks: {
    authorized: ({ auth }) => {
      return !!auth;
    },
  },
 
  trustHost: true,
});
 
const getUser = (credentials) => {
  if (credentials) {
    const user = users[credentials.email];
 
    if (user && user.password === credentials.password) {
      return {
        name: user.name,
        email: credentials.email,
      };
    }
  }
 
  return null;
};

5. Создаём список пользователей users.js в папке data:

data/users.js
export const users = {
  "gorbunkov@diamond.ru": {
    name: "Семён Семёныч Горбунков",
    password: "...",
  },
  "bunsha@profession.ru": {
    name: "Иван Васильевич Бунша",
    password: "...",
  },
};

Напоминаю, что пароли пользователей не рекомендуется хранить в открытом виде. Следует использовать хеширование перед сохранением пароля, например, с помощью библиотеки bcrypt. Во время аутентификации необходимо сверять хеш введённого пароля с хешем сохранённого.

6. Создаём файл .env или добавляем в существующий файл .env переменные окружения:

.env
AUTH_URL=https://example.ru/api/auth
AUTH_SECRET=88c4558b278ba963e14698f9e18637e3230ae4489d7f903fc0c6e2581f0d99d6

Сгенерировать уникальный AUTH_SECRET можно командой в терминале:

terminal
npx auth secret

Теперь, при переходе в админку Keystatic CMS, будет запрашиваться логин и пароль для входа.