2026-09-03 09:16:56 +03:00
|
|
|
|
# AuthService
|
|
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
`authservice.h`, `authservice.cpp`
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
Вход через Ely.by, офлайн-профиль и загрузка `authlib-injector`. Вход через Microsoft живёт
|
|
|
|
|
|
отдельно, в [MsaAuthService](MsaAuthService.md), но отдаёт результат в той же структуре
|
|
|
|
|
|
`AuthResult`. Поэтому запуск игры дальше идёт одинаково, как бы игрок ни вошёл.
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
Экземпляр создаёт и держит [LauncherBackend](LauncherBackend.md). Сервис ничего не пишет на диск,
|
|
|
|
|
|
кроме скачанного jar: токены между запусками сохраняет бэкенд в `profiles.json`.
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
## AuthResult
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
Каждое поле соответствует подстановке в аргументах запуска.
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
| Поле | Подстановка / смысл |
|
|
|
|
|
|
|------|---------------------|
|
|
|
|
|
|
| `ok` | вход удался |
|
|
|
|
|
|
| `twoFactorRequired` | Ely.by требует одноразовый код |
|
|
|
|
|
|
| `licenseMissing` | Microsoft: вход прошёл, но игры на аккаунте нет. Отдельный флаг, потому что повторный вход тут не поможет |
|
|
|
|
|
|
| `error` | текст ошибки, если `ok == false` |
|
|
|
|
|
|
| `playerName` | `${auth_player_name}` |
|
|
|
|
|
|
| `uuid` | `${auth_uuid}`, hex без дефисов |
|
|
|
|
|
|
| `accessToken` | `${auth_access_token}` |
|
|
|
|
|
|
| `clientToken` | `${clientid}` |
|
|
|
|
|
|
| `userType` | `${user_type}`: `legacy` (офлайн), `ELYBY`, `msa` |
|
|
|
|
|
|
| `refreshToken` | только Microsoft: продление сессии без пароля |
|
|
|
|
|
|
| `xuid` | только Microsoft: `${auth_xuid}` |
|
|
|
|
|
|
| `expiresAt` | только Microsoft: когда истекает `accessToken`, UTC |
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
## Офлайн
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
`static AuthResult offline(nickname)` работает без сети. UUID считается так же, как в самом
|
|
|
|
|
|
Minecraft: MD5 от `OfflinePlayer:<ник>`, после чего выставляются биты версии 3 и варианта RFC 4122.
|
|
|
|
|
|
Значит, у одного ника всегда один UUID, и на офлайн-сервере игрок не теряет инвентарь. В
|
|
|
|
|
|
`accessToken` и `clientToken` записывается `"0"`.
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
Пустой ник — ошибка.
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
## Ely.by
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
Сервер — `https://authserver.ely.by`, протокол Yggdrasil, JSON по HTTPS.
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
`loginElyBy(login, password, clientToken, accessToken, callback)` старается не спрашивать пароль:
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
1. Если сохранённого `accessToken` нет, сразу `/auth/authenticate` с паролем.
|
|
|
|
|
|
2. Если есть, `/auth/validate`. Ответ 200 — токен рабочий, вход закончен.
|
|
|
|
|
|
3. Иначе `/auth/refresh`. Если продлить удалось, приходят новый токен, ник и UUID.
|
|
|
|
|
|
4. Если и это не вышло, `/auth/authenticate` с паролем.
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
Если сервер недоступен (статус 0 и сетевая ошибка), цепочка обрывается с ошибкой, без попытки войти
|
|
|
|
|
|
по паролю.
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
Второй фактор Ely.by не сообщает отдельным кодом. Сервис ищет в тексте ошибки подстроку
|
|
|
|
|
|
`two factor` и выставляет `twoFactorRequired`. Тогда бэкенд спрашивает код у игрока и вызывает
|
|
|
|
|
|
`loginElyByWithTotp(login, password, totp, clientToken, callback)`, который отправляет пароль в виде
|
|
|
|
|
|
`пароль:код`, как требует Ely.by.
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
`clientToken` генерируется один раз на профиль (`generateClientToken()`, случайный UUID) и хранится
|
|
|
|
|
|
вместе с ним: Yggdrasil привязывает выданный `accessToken` к этому значению.
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
По ходу работы испускается `progress(message)`. Бэкенд пересылает его в `launchProgress`.
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
## authlib-injector
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
Без него игра пойдёт проверять сессию на серверы Mojang, и токен Ely.by окажется недействительным.
|
|
|
|
|
|
Jar подключается к JVM через `-javaagent` (см. [GameLauncher](GameLauncher.md)).
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
`ensureAuthlibInjector(targetDir, callback)`:
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
- если `<targetDir>/authlib-injector.jar` уже есть, сразу отдаёт путь. Версия не проверяется, и
|
|
|
|
|
|
обновить файл можно, только удалив его;
|
|
|
|
|
|
- иначе читает `https://authlib-injector.yushi.moe/artifact/latest.json`, скачивает jar по
|
|
|
|
|
|
`download_url` и, если в манифесте есть `checksums.sha256`, сверяет хеш.
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
Колбэк получает либо путь, либо текст ошибки. `targetDir` — это `<root>/runtime`.
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
## Как вызываются колбэки
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
Все сетевые методы асинхронные, колбэк вызывается один раз в GUI-потоке. Если сервис удалить во
|
|
|
|
|
|
время запроса, менеджер сети уйдёт вместе с ним, и колбэк не вызовется вообще. Бэкенд к тому же
|
|
|
|
|
|
проверяет в каждом колбэке, не отменили ли запуск, пока шёл запрос.
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
2026-10-11 22:32:13 +03:00
|
|
|
|
Повторных попыток при сетевых ошибках нет.
|
2026-09-03 09:16:56 +03:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
При создании этого документа использовался ИИ.
|