5.9 KiB
MsaAuthService
msaauthservice.h, msaauthservice.cpp
Вход через аккаунт Microsoft, то есть с лицензионной копией игры. Цепочка такая же, как у
официального лаунчера: OAuth2 → Xbox Live → XSTS → Minecraft Services → проверка лицензии →
профиль. Результат приходит в AuthResult из AuthService.
Окно входа сервис не показывает. Страницу Microsoft открывает MicrosoftLoginDialog, а сервис даёт адрес этой страницы и умеет узнать адрес возврата. Класс компилируется всегда, но без Qt WebEngine показать страницу нечем, и LauncherBackend сразу отвечает ошибкой.
Чьё это приложение
Сейчас используется client_id официального лаунчера Mojang (00000000402b5328). Это старое
приложение Live Connect, поэтому и адреса от login.live.com:
| Константа | Значение |
|---|---|
kAuthorizeUrl |
https://login.live.com/oauth20_authorize.srf |
kTokenUrl |
https://login.live.com/oauth20_token.srf |
kRedirectUri |
https://login.live.com/oauth20_desktop.srf |
kScope |
service::user.auth.xboxlive.com::MBI_SSL |
kRpsTicketPrefix |
пусто |
Это временное решение. Чтобы перейти на своё приложение в Azure (с включённым «Allow public client
flows»), меняются эти шесть констант. Что именно подставить, написано в комментарии в начале
msaauthservice.cpp. Главное, что легко пропустить: у нового приложения в RpsTicket нужна
приставка d=.
clientId() отдаёт этот id наружу. Бэкенд подставляет его в ${clientid}, потому что официальный
лаунчер передаёт туда id приложения, а не случайный токен.
Окно входа
authorizationUrl() — адрес страницы входа с client_id, response_type=code, redirect_uri,
scope и prompt=select_account. Последний параметр нужен, чтобы при повторном входе можно было
выбрать другой аккаунт.
matchRedirect(url, &code, &error) возвращает true, только если хост и путь совпадают с
kRedirectUri. Код или ошибка ищутся сначала в query, потом во фрагменте. В error попадает
error_description, а если его нет, то error. Эта проверка сделана в C++, а не в QML, чтобы она
всегда совпадала с тем адресом, который сервис сам передаёт в redirect_uri.
Цепочка
loginWithCode(code, callback) меняет код на токен (grant_type=authorization_code).
loginWithRefreshToken(refreshToken, callback) делает то же по refresh-токену. Дальше путь общий:
- Токен Microsoft. Форма на
kTokenUrl. Из ответа берутсяaccess_tokenиrefresh_token. - Xbox Live.
user.auth.xboxlive.com/user/authenticate,RpsTicket= приставка + токен Microsoft. - XSTS.
xsts.auth.xboxlive.com/xsts/authorizeдляrp://api.minecraftservices.com/. При 401 кодXErrпереводится в понятный текст: нет профиля Xbox, страна не поддерживается, нужна проверка возраста, детский аккаунт без разрешения взрослого. Отсюда же берутсяuhsиxid(он станетxuid). - Minecraft Services.
login_with_xboxсXBL3.0 x=<uhs>;<xsts>. В ответе токен Minecraft иexpires_in, обычно сутки; от него считаетсяexpiresAt. - Лицензия.
entitlements/mcstore. Результат только запоминается и сам вход не останавливает. - Профиль.
minecraft/profile. Ответы 404 и 401 означают, что профиля нет: выставляетсяlicenseMissing. Текст ошибки зависит от шага 5. Если игра куплена, значит, игрок ещё не выбрал ник. Если не куплена, значит, лицензии нет.
userType = msa, clientToken = id приложения.
Каждый шаг испускает progress(message) до отправки запроса. Таймаут на каждый запрос 20 секунд,
повторных попыток нет. Сетевая ошибка и отказ сервера дают разные тексты.
Refresh-токен Microsoft живёт намного дольше суточного токена Minecraft, поэтому при обычном
запуске окно входа не нужно: бэкенд вызывает loginWithRefreshToken(). Если Microsoft не вернул
новый refresh-токен, бэкенд оставляет старый.
Колбэки
Колбэк вызывается один раз в GUI-потоке. Шаги вызываются из колбэков предыдущих. Если удалить сервис посреди цепочки, она оборвётся вместе с менеджером сети, и колбэк не вызовется.
При создании этого документа использовался ИИ.