Перейти к содержимому

Аутентификация

Laminara не хранит аккаунты. Логины и пароли остаются там, где они у вас уже есть — в базе сайта, в отдельном файле или за вашим API. Laminara обращается к этому источнику через адаптер, проверяет пару логин/пароль и владеет только сессиями.

Раздел auth состоит из трёх частей: провайдер (откуда аккаунты), хеш пароля и хранилище сессий. Все куски ниже — части этого раздела в конфиге сервера (/etc/laminara/config.json), а не в настройках сборки.

Провайдеры

Аккаунты в JSON-файле. Годится для небольшого списка или на старте.

{
"provider": "jsonfile",
"config": {
"path": "/var/lib/laminara/users.json",
"hash": "argon2id",
"fields": { "username": "username", "password": "password", "uuid": "uuid" }
},
"sessions": { "backend": "memory" }
}

Заводить игроков руками не нужно — это делает команда:

Окно терминала
laminara-server exec "auth add Steve" # пароль придумается сам и покажется один раз
laminara-server exec "auth add Steve пароль" # или задайте свой
laminara-server exec "auth passwd Steve" # сменить пароль
laminara-server exec "auth remove Steve" # убрать игрока
laminara-server exec "auth list" # кто заведён

Команда сама считает хеш той схемой, что стоит в hash, кладёт постоянный uuid и пишет файл целиком — испортить его опечаткой нельзя. Новый игрок может входить сразу, перезапускать проект не нужно.

Править файл руками тоже можно: он перечитывается, как только меняется. Формат — массив объектов, минимально нужны ник и хеш пароля (посчитать: laminara-server hash <пароль>):

[
{ "username": "Steve", "password": "$argon2id$v=19$m=65536,t=1,p=2$c29tZXNhbHQ$…" },
{ "username": "Alex", "password": "$argon2id$v=19$m=65536,t=1,p=2$b3RoZXJzYWx0$…" }
]

С постоянным uuid — тогда смена ника не обнулит прогресс игрока:

[
{
"username": "Steve",
"password": "$2a$12$…",
"uuid": "8667ba71-b85a-4004-af54-457a9734eed7"
}
]

С двухфакторной аутентификацией у отдельного игрока:

[
{ "username": "Steve", "password": "$argon2id$…", "totp": "JBSWY3DPEHPK3PXP" },
{ "username": "Alex", "password": "$argon2id$…" }
]

Если файл уже существует и ключи в нём называются иначе, подстройте fields под него, а не наоборот:

"config": {
"path": "/var/lib/laminara/players.json",
"hash": "bcrypt",
"fields": {
"username": "nick",
"password": "pass_hash",
"uuid": "player_uuid",
"twoFactorSecret": "totp_secret"
}
}
[
{ "nick": "Steve", "pass_hash": "$2a$12$…", "player_uuid": "8667ba71-…" }
]

Хеш для файла считает команда laminara-server hash (--algo, а для bcrypt ещё и --cost). Файл читается один раз при старте, поэтому после правок проект нужно перезапустить.

Хеш пароля

Поле hash (у jsonfile и sql) говорит, как пароль захеширован в вашем источнике. Laminara хеширует введённый пароль тем же способом и сравнивает. Доступны:

argon2id · bcrypt · sha256 · sha512 · md5 · plain

Без этого поля берётся argon2id. Схему указывают под свою базу: если она не совпадёт с настоящей, вход не пройдёт ни у кого и сервер скажет, что хранимый пароль не читается.

Двухфакторная аутентификация

Второй фактор — одноразовый код из приложения-аутентификатора (TOTP): подойдёт Google Authenticator, Яндекс.Ключ и любое совместимое приложение. Включается на игрока, а не на весь проект: у кого секрет есть, тот входит по паролю и коду, у кого нет — как раньше.

Секрет выпускает консоль:

auth totp <игрок>

Команда печатает base32-секрет и строку otpauth:// — приложение-аутентификатор подхватит из неё коды. Секрет впишите игроку в источник аккаунтов (как именно — зависит от провайдера, см. ниже), и вход без кода закроется; sql подхватывает секрет сразу, jsonfile — после перезапуска проекта. Отключить двухфакторку так же просто: уберите секрет. Игрок потерял телефон — выпустите новый секрет и попросите добавить его заново.

Ключ записи, по умолчанию totp (меняется полем fields.twoFactorSecret):

{ "username": "neo", "password": "…", "totp": "JBSWY3DPEHPK3PXP" }

Код меняется каждые 30 секунд; принимается код текущего и соседних интервалов, чтобы часы не обязаны совпадать до секунды. Один и тот же код принимается дважды — лаунчер проверяет его в двух шагах входа; третий раз не пройдёт.

Сессии

Пароль проверяется один раз; дальше клиент живёт по токенам, которые выдаёт и хранит Laminara. Токен доступа короткий, токен обновления — длинный. При обновлении старый токен отзывается, а попытка воспользоваться отозванным распознаётся.

  • backend: "memory" — сессии в памяти процесса. Просто, но не переживают перезапуск и не годятся для нескольких экземпляров.
  • backend: "redis" с блоком redis (addr, при необходимости password, db, tls) — сессии в Redis: переживают перезапуск и общие для нескольких экземпляров сервера. Старое поле redisAddr рядом с backend тоже понимается, чтобы конфиги прошлых версий продолжали работать.

Эта настройка распоряжается обеими сессиями игрока: и входом в лаунчер, и входом в игре через yggdrasil. На memory перезапуск сервера выкидывает игроков из лаунчера, и им приходится вводить пароль заново — даже если Redis у вас стоит и работает для чего-то другого. Что именно выбрано, показывает doctor двумя строками: «сессии» и «сессии в игре».

Сроки жизни токенов задаются полями accessTTL и refreshTTL рядом с provider (например, "15m" и "720h").