# AuthService `authservice.h`, `authservice.cpp` Вход через Ely.by, офлайн-профиль и загрузка `authlib-injector`. Вход через Microsoft живёт отдельно, в [MsaAuthService](MsaAuthService.md), но отдаёт результат в той же структуре `AuthResult`. Поэтому запуск игры дальше идёт одинаково, как бы игрок ни вошёл. Экземпляр создаёт и держит [LauncherBackend](LauncherBackend.md). Сервис ничего не пишет на диск, кроме скачанного jar: токены между запусками сохраняет бэкенд в `profiles.json`. ## AuthResult Каждое поле соответствует подстановке в аргументах запуска. | Поле | Подстановка / смысл | |------|---------------------| | `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 | ## Офлайн `static AuthResult offline(nickname)` работает без сети. UUID считается так же, как в самом Minecraft: MD5 от `OfflinePlayer:<ник>`, после чего выставляются биты версии 3 и варианта RFC 4122. Значит, у одного ника всегда один UUID, и на офлайн-сервере игрок не теряет инвентарь. В `accessToken` и `clientToken` записывается `"0"`. Пустой ник — ошибка. ## Ely.by Сервер — `https://authserver.ely.by`, протокол Yggdrasil, JSON по HTTPS. `loginElyBy(login, password, clientToken, accessToken, callback)` старается не спрашивать пароль: 1. Если сохранённого `accessToken` нет, сразу `/auth/authenticate` с паролем. 2. Если есть, `/auth/validate`. Ответ 200 — токен рабочий, вход закончен. 3. Иначе `/auth/refresh`. Если продлить удалось, приходят новый токен, ник и UUID. 4. Если и это не вышло, `/auth/authenticate` с паролем. Если сервер недоступен (статус 0 и сетевая ошибка), цепочка обрывается с ошибкой, без попытки войти по паролю. Второй фактор Ely.by не сообщает отдельным кодом. Сервис ищет в тексте ошибки подстроку `two factor` и выставляет `twoFactorRequired`. Тогда бэкенд спрашивает код у игрока и вызывает `loginElyByWithTotp(login, password, totp, clientToken, callback)`, который отправляет пароль в виде `пароль:код`, как требует Ely.by. `clientToken` генерируется один раз на профиль (`generateClientToken()`, случайный UUID) и хранится вместе с ним: Yggdrasil привязывает выданный `accessToken` к этому значению. По ходу работы испускается `progress(message)`. Бэкенд пересылает его в `launchProgress`. ## authlib-injector Без него игра пойдёт проверять сессию на серверы Mojang, и токен Ely.by окажется недействительным. Jar подключается к JVM через `-javaagent` (см. [GameLauncher](GameLauncher.md)). `ensureAuthlibInjector(targetDir, callback)`: - если `/authlib-injector.jar` уже есть, сразу отдаёт путь. Версия не проверяется, и обновить файл можно, только удалив его; - иначе читает `https://authlib-injector.yushi.moe/artifact/latest.json`, скачивает jar по `download_url` и, если в манифесте есть `checksums.sha256`, сверяет хеш. Колбэк получает либо путь, либо текст ошибки. `targetDir` — это `/runtime`. ## Как вызываются колбэки Все сетевые методы асинхронные, колбэк вызывается один раз в GUI-потоке. Если сервис удалить во время запроса, менеджер сети уйдёт вместе с ним, и колбэк не вызовется вообще. Бэкенд к тому же проверяет в каждом колбэке, не отменили ли запуск, пока шёл запрос. Повторных попыток при сетевых ошибках нет. --- При создании этого документа использовался ИИ.