5.6 KiB
AuthService
authservice.h, authservice.cpp
Вход через Ely.by, офлайн-профиль и загрузка authlib-injector. Вход через Microsoft живёт
отдельно, в MsaAuthService, но отдаёт результат в той же структуре
AuthResult. Поэтому запуск игры дальше идёт одинаково, как бы игрок ни вошёл.
Экземпляр создаёт и держит LauncherBackend. Сервис ничего не пишет на диск,
кроме скачанного 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) старается не спрашивать пароль:
- Если сохранённого
accessTokenнет, сразу/auth/authenticateс паролем. - Если есть,
/auth/validate. Ответ 200 — токен рабочий, вход закончен. - Иначе
/auth/refresh. Если продлить удалось, приходят новый токен, ник и UUID. - Если и это не вышло,
/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).
ensureAuthlibInjector(targetDir, callback):
- если
<targetDir>/authlib-injector.jarуже есть, сразу отдаёт путь. Версия не проверяется, и обновить файл можно, только удалив его; - иначе читает
https://authlib-injector.yushi.moe/artifact/latest.json, скачивает jar поdownload_urlи, если в манифесте естьchecksums.sha256, сверяет хеш.
Колбэк получает либо путь, либо текст ошибки. targetDir — это <root>/runtime.
Как вызываются колбэки
Все сетевые методы асинхронные, колбэк вызывается один раз в GUI-потоке. Если сервис удалить во время запроса, менеджер сети уйдёт вместе с ним, и колбэк не вызовется вообще. Бэкенд к тому же проверяет в каждом колбэке, не отменили ли запуск, пока шёл запрос.
Повторных попыток при сетевых ошибках нет.
При создании этого документа использовался ИИ.