89 lines
5.6 KiB
Markdown
89 lines
5.6 KiB
Markdown
# 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)`:
|
||
|
||
- если `<targetDir>/authlib-injector.jar` уже есть, сразу отдаёт путь. Версия не проверяется, и
|
||
обновить файл можно, только удалив его;
|
||
- иначе читает `https://authlib-injector.yushi.moe/artifact/latest.json`, скачивает jar по
|
||
`download_url` и, если в манифесте есть `checksums.sha256`, сверяет хеш.
|
||
|
||
Колбэк получает либо путь, либо текст ошибки. `targetDir` — это `<root>/runtime`.
|
||
|
||
## Как вызываются колбэки
|
||
|
||
Все сетевые методы асинхронные, колбэк вызывается один раз в GUI-потоке. Если сервис удалить во
|
||
время запроса, менеджер сети уйдёт вместе с ним, и колбэк не вызовется вообще. Бэкенд к тому же
|
||
проверяет в каждом колбэке, не отменили ли запуск, пока шёл запрос.
|
||
|
||
Повторных попыток при сетевых ошибках нет.
|
||
|
||
---
|
||
|
||
При создании этого документа использовался ИИ.
|