Skip to content

DimaSergeew/AuthSecurity

Repository files navigation

🔐 AuthSecurity

Гейт авторизации для Paper / Folia прямо в configuration phase
Игрок не попадает в мир, пока не введёт пароль. Без лимба, без временных миров, без телепортов.

Java 25 Paper 1.21.11 Folia Argon2id H2 / MariaDB


✨ Возможности

Фича Описание
🚪 Config-phase gate Блокировка в AsyncPlayerConnectionConfigureEvent — игрок физически не грузится в мир.
🔑 Argon2id password4j, 19 MiB / 2 iter / 16-byte salt. Параметры зафиксированы.
🗄 H2 / MariaDB HikariCP + prepared statements из .sql ресурсов.
🌐 IP-лимит Макс. N одновременных аккаунтов с одного IP.
Trusted sessions Повторный вход с того же IP в течение TTL — без диалога.
🅰 Password policy Опционально: обязательна буква + цифра.
🔡 Case-sensitive login Регистр логина проверяется — «другой регистр» вежливо отклоняется.
🚪 Force logout Админ может разлогинить игрока и инвалидировать trusted-сессию.
Hot reload /authsecurity reload без рестарта (кроме секции database).
💬 Forgot password Inline-диалог с кнопкой-ссылкой на Discord.
Brigadier-команды Cloud annotations + нативное автодополнение.
🌸 Folia-ready AsyncScheduler, корректная обработка событий по регионам.
📝 MiniMessage Все сообщения строго типизированы (records).

🚀 Установка

# 1. Скачайте AuthSecurity.jar (Releases) или соберите:
./gradlew shadowJar      # → build/libs/AuthSecurity.jar

# 2. Скопируйте в plugins/, запустите сервер.
# 3. Отредактируйте plugins/AuthSecurity/config.yml.
# 4. /authsecurity reload — применить без рестарта.

Требования: Java 25 · Paper API 1.21.11 · Folia опционально.


🧭 Команды

Команда Назначение Право Default
/changepassword Смена своего пароля (диалогом). authsecurity.changepassword all
/changepassword <player> <newpass> Принудительная смена пароля. authsecurity.admin.changepassword op
/unregister <player> Удалить регистрацию. authsecurity.admin.unregister op
/accountinfo <player> UUID, IP, даты создания/обновления. authsecurity.admin.accountinfo op
/authsecurity trustip off Отключить быстрый вход с текущего IP. - all
/authsecurity trustip on Включить быстрый вход обратно. - all
/authsecurity reload Перечитать конфиг без рестарта. authsecurity.admin.reload op
/authsecurity logout <player> Разлогинить + инвалидировать trust. authsecurity.admin.logout op

💡 Смена пароля инвалидирует trusted-сессию — игрок должен залогиниться заново.


⚙️ Конфигурация

plugins/AuthSecurity/config.yml — кликабельно
database:
  type: "h2"                    # "h2" | "mariadb"
  h2:
    file: "players"
    options: "AUTO_SERVER=FALSE;MODE=MySQL"
  mariadb:
    host: "127.0.0.1"
    port: 3306
    database: "authsecurity"
    username: "auth"
    password: "change-me"
    parameters: "useSSL=false&autoReconnect=true&characterEncoding=utf8"
  pool:
    maximum-pool-size: 8
    minimum-idle: 2
    connection-timeout-millis: 5000

security:
  max-attempts: 5               # попыток за сессию диалога
  session-ttl-minutes: 30       # TTL trusted-сессии; включена по умолчанию (0 = всегда спрашивать)
  login-timeout-minutes: 3      # таймаут диалога
  password-min-length: 6
  password-max-length: 72
  accounts-per-ip-limit: 3      # одновременных аккаунтов с IP

  password-policy:
    require-letter-and-digit: false

support:
  discord-url: "https://discord.gg/your-invite-here"

messages:
  login-title: "<gold>🔐 Login</gold>"
  # ... полный набор сообщений — MiniMessage

Плейсхолдеры: <username>, <remaining>, <limit>, <player>, <min>, <max>, <minutes>, <correct>, <key>, <value>. Формат: MiniMessage.

⚠️ Секция database не применяется через /authsecurity reload — Hikari держит открытые соединения. Всё остальное hot-reloadable.


🧩 Поток авторизации

Player connects
       │
       ▼
AsyncPlayerConnectionConfigureEvent  (async)
       │
  ┌────┼──────────────┬──────────────┬──────────────┐
  ▼                   ▼              ▼              ▼
IP trusted?    IP limit hit?   Locked out?   Username case OK?
  skip            disconnect     disconnect    disconnect (hint)
                                       │
                                       ▼
                                 Show Dialog
                                       │
                                future().join()  ← блок до submit
                                       │
                            PlayerCustomClickEvent
                                       │
              ┌────────────────────────┼─────────────────┐
              ▼                        ▼                 ▼
           submit                   cancel        forgot-password
              │                        │                 │
              ▼                        ▼                 ▼
        Argon2 verify             disconnect       inline dialog
       /         \                                  (Discord URL)
      ✓           ✗
      │           │
      ▼           ▼
 complete(future)  retry / kick after max-attempts
      │
      ▼
 player enters world

🏗 Архитектура

Дерево проекта
src/main/java/me/bedepay/authsecurity
├── AuthSecurity.java              — entry point, wiring, reload()
├── auth/
│   ├── AuthFlow.java              — config-phase gate + click handler
│   ├── PendingSession.java        — record ожидающей сессии
│   ├── AuthResult.java            — record результата
│   ├── PasswordHasher.java        — Argon2id wrapper
│   └── PasswordPolicy.java        — общие правила паролей
├── commands/
│   ├── AuthCommands.java          — /unregister, /changepassword, /accountinfo
│   └── AdminCommands.java         — /authsecurity reload · logout
├── config/
│   ├── PluginConfig.java          — record всего конфига
│   ├── Messages.java              — record сообщений (MiniMessage)
│   └── ConfigLoader.java          — YAML → records
├── dialog/Dialogs.java            — фабрика диалогов
├── ip/ConnectionTracker.java      — учёт подключений по IP
└── storage/
    ├── Account.java               — record строки БД
    ├── AccountRepository.java     — интерфейс
    ├── HikariAccountRepository.java — H2 / MariaDB реализация
    └── SqlBundle.java             — загрузка .sql из resources

src/main/resources
├── config.yml · paper-plugin.yml · psw4j.properties
└── sql/{h2,mariadb}/*.sql         — LOWER(username)=LOWER(?) везде

🛑 Инварианты (не трогать)

  • future().join() в AuthFlow.onConfigure — именно он держит игрока в config-phase.
  • canCloseWithEscape(false) на login/register — иначе можно прорваться мимо.
  • Параметры Argon2id менять нельзя без миграции хешей.
  • SQL — только в ресурсах и только через PreparedStatement.
  • При любой новой записи в trustedSessions — планировать expiry через scheduleTrustExpiry(uuid) (отменяет старую задачу, иначе гонка).
  • findByUsername использует LOWER(...) — на этом держится проверка «неверный регистр».

🧪 Разработка

./gradlew shadowJar        # сборка плагина
./gradlew build            # compile + shadowJar (тесты отключены)

Все runtime-зависимости (Hikari, H2, MariaDB, Cloud, password4j) затеняются и релокейтятся под me.bedepay.authsecurity.libs.*.

Добавить сообщение
  1. Поле в Messages.java (record).
  2. Парсинг в ConfigLoader.readMessages.
  3. Дефолт в src/main/resources/config.yml.
  4. Для плейсхолдеров — метод-рендер через Placeholder.unparsed(...).
Добавить команду
@Command("mycommand <arg>")
@Permission("authsecurity.admin.mycommand")
public void myCommand(CommandSourceStack source, @Argument("arg") String arg) { ... }

Парсер сканирует AuthCommands / AdminCommands в AuthSecurity#onEnable. Не забыть добавить permission в paper-plugin.yml.

Добавить конфиг-параметр
  1. Запись в config.yml с комментарием.
  2. Поле в соответствующем record'е PluginConfig.
  3. Чтение в ConfigLoader с дефолтом.
  4. Если hot-reloadable — пробросить через applyConfig(...) компонента в AuthSecurity.reload().

🛡 Безопасность

  • Пароли — Argon2id, никогда не логируются.
  • Lockout переживает реконнект — брутфорс через новое TCP-соединение не помогает.
  • Idle kick разлогинивает отошедших игроков, защищая от захвата сессии.
  • /changepassword <player> <pass> оставляет пароль в истории — только для сервисных задач; смена пароля инвалидирует trusted-сессию.
  • Таблица accounts: UUID, username, hash, служебные поля. Никакого plaintext.

© bedepay · GitHub · Лицензия: TODO (MIT / Apache 2.0)

About

Плагин авторизации для Paper/Folia, удерживающий игрока в configuration phase до успешного логина. H2/MariaDB, Hikari, Argon2id, IP-лимит, Brigadier команды.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors