Files
BiLauncher/doc/cpp/MsaAuthService.md
T
2026-10-11 22:32:13 +03:00

5.9 KiB
Raw Permalink Blame History

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-токену. Дальше путь общий:

  1. Токен Microsoft. Форма на kTokenUrl. Из ответа берутся access_token и refresh_token.
  2. Xbox Live. user.auth.xboxlive.com/user/authenticate, RpsTicket = приставка + токен Microsoft.
  3. XSTS. xsts.auth.xboxlive.com/xsts/authorize для rp://api.minecraftservices.com/. При 401 код XErr переводится в понятный текст: нет профиля Xbox, страна не поддерживается, нужна проверка возраста, детский аккаунт без разрешения взрослого. Отсюда же берутся uhs и xid (он станет xuid).
  4. Minecraft Services. login_with_xbox с XBL3.0 x=<uhs>;<xsts>. В ответе токен Minecraft и expires_in, обычно сутки; от него считается expiresAt.
  5. Лицензия. entitlements/mcstore. Результат только запоминается и сам вход не останавливает.
  6. Профиль. minecraft/profile. Ответы 404 и 401 означают, что профиля нет: выставляется licenseMissing. Текст ошибки зависит от шага 5. Если игра куплена, значит, игрок ещё не выбрал ник. Если не куплена, значит, лицензии нет.

userType = msa, clientToken = id приложения.

Каждый шаг испускает progress(message) до отправки запроса. Таймаут на каждый запрос 20 секунд, повторных попыток нет. Сетевая ошибка и отказ сервера дают разные тексты.

Refresh-токен Microsoft живёт намного дольше суточного токена Minecraft, поэтому при обычном запуске окно входа не нужно: бэкенд вызывает loginWithRefreshToken(). Если Microsoft не вернул новый refresh-токен, бэкенд оставляет старый.

Колбэки

Колбэк вызывается один раз в GUI-потоке. Шаги вызываются из колбэков предыдущих. Если удалить сервис посреди цепочки, она оборвётся вместе с менеджером сети, и колбэк не вызовется.


При создании этого документа использовался ИИ.