Async Python client for Microsoft → Minecraft authentication and the Mojang REST APIs (typed, httpx-based)
Project description
mcapi-auth
⚠️ Project status: alpha. API surface may change without warning until 1.0.
Async, typed Python library that covers both halves of "talking to the Mojang/Microsoft Minecraft stack":
- Auth (
mcapi_auth.auth) — the 5-stage Microsoft → Xbox → Mojang handshake to turn a Microsoft account into a Minecraft access token + UUID + username, plus the related helpers (auth-code/PKCE, browser redirect listener, cookie-based silent flows, entitlements, joinServer, refresh-token storage, JWT decode). - API (
mcapi_auth.api) — the public + authed Mojang/Minecraft REST surface: UUID lookups, public profile + texture decode, blocked servers, authed profile / skin / cape / name endpoints, piston-meta version manifest.
This is the merger of the previously separate mcauth and mcapi
packages; see CHANGELOG.md for the migration notes.
Requires Python 3.14+. Runtime dependencies: httpx, pydantic >= 2,
whenever >= 0.10.
Installation
pip install mcapi-auth # once published
# or, from source:
git clone git@github.com:clawdbot-silly-waddle/mcapi-auth.git
cd mcapi-auth
uv sync
Quickstart — auth + a couple of API calls
import asyncio
from mcapi_auth import login_device_code_v1, get_own_profile, get_uuid_by_name
async def main() -> None:
session = await login_device_code_v1() # Microsoft → Minecraft token
# Pass ``storage=FileTokenStorage()`` to persist the refresh token
# across runs — by default tokens live only in memory.
print(session.username, session.uuid_dashed)
profile = await get_own_profile(session) # accepts session or raw str
print(profile.skins, profile.capes)
other = await get_uuid_by_name("Notch") # public lookup, no auth
print(other)
asyncio.run(main())
First run: a URL + 8-character code is printed; visit, paste, sign in.
To persist the refresh token across runs (so subsequent launches skip
the interactive step), pass storage=FileTokenStorage() to
login_device_code_v1(). The default NullTokenStorage keeps state in memory
only.
Synchronous usage
If you can't or don't want to write async code (one-off scripts, Django/Flask views), use the sync facade — every public async function is exposed as a blocking wrapper that runs in a fresh event loop:
from mcapi_auth import sync as mcapi
session = mcapi.login() # blocks until done
profile = mcapi.get_own_profile(token=session.access_token)
print(profile.name, profile.id)
Caveats:
- Each call spins up a fresh
asyncio.run(...)loop — fine for ad-hoc scripts, not great if you want connection pooling across many calls. - Do not call
mcapi_auth.sync.*from inside a running asyncio loop. It will raise — use the async API directly in that case. - The full async surface (~73 functions including
login,refresh_*,get_*,change_*,fetch_*,is_*,accept_*,start_*) is available.from mcapi_auth import sync; dir(sync)lists them.
Package layout
mcapi_auth/
├── auth/ # token-chain stages, cookie flows, storage, JWT decode
├── api/ # public lookups + authed profile/skin/cape/name + piston-meta
└── exceptions # unified McApiAuthError tree (McAuthError + McApiError)
Everyday names are re-exported from the top level so most code can do
from mcapi_auth import X. Reach into the subpackages for niche
helpers (e.g. from mcapi_auth.auth.auth_code import ... for the
PKCE flow).
Browser-driven login (no codes to type)
If your app can open a browser, login_browser_v2() is friendlier:
it spins up a localhost listener, opens the MSA authorize URL, catches
the redirect, and validates CSRF state — all stdlib, no extra deps.
from mcapi_auth import login_browser_v2
session = await login_browser_v2(prompt="select_account")
See examples/browser_login.py for a
runnable script.
Custom prompt display
from mcapi_auth import DeviceCodePrompt, login_device_code_v1
async def show(prompt: DeviceCodePrompt) -> None:
await channel.send(
f"Sign in here within {prompt.expires_in}s: {prompt.verification_uri}\n"
f"Code: `{prompt.user_code}`"
)
session = await login_device_code_v1(on_device_code=show)
Custom token storage
from mcapi_auth import TokenStorage, login_device_code_v1
class MemoryStorage(TokenStorage):
def __init__(self) -> None:
self._token: str | None = None
async def load(self) -> str | None: return self._token
async def save(self, refresh_token: str) -> None: self._token = refresh_token
async def clear(self) -> None: self._token = None
session = await login_device_code_v1(storage=MemoryStorage())
The default storage (FileTokenStorage) writes JSON to
$XDG_STATE_HOME/mcapi_auth/refresh_token.json (falling back to
~/.local/state/mcapi_auth/refresh_token.json) with 0600 permissions
and atomic replace on save.
Public API endpoints
The mcapi_auth.api half wraps Mojang's public + authed REST surface:
from mcapi_auth import (
# public — no auth
get_uuid_by_name, get_uuids_by_names, get_profile_by_uuid,
extract_textures, fetch_blocked_servers, is_server_blocked,
fetch_version_manifest,
# authed — pass a session or a raw access-token str
get_own_profile, change_skin_from_url, change_skin_from_file,
reset_skin, change_cape, disable_cape,
check_name_availability, change_name, get_name_change_eligibility,
)
uuid = await get_uuid_by_name("Notch")
profile = await get_profile_by_uuid(uuid.id)
decoded = extract_textures(profile) # skin URL, cape URL, slim/classic
print(decoded.skin.url, decoded.skin.model)
manifest = await fetch_version_manifest()
print(manifest.latest_release, manifest.latest_snapshot)
Every authed endpoint accepts either a raw access-token string or any
object exposing an .access_token attribute — which is exactly what
MinecraftSession provides, so you can pass the result of login_device_code_v1()
directly.
Typed errors
Two parallel hierarchies live under a single root:
McApiAuthError
├── McAuthError (auth-chain failures)
│ ├── MSAAuthError
│ │ ├── MSAFlowError
│ │ ├── DeviceCodeExpiredError
│ │ └── AuthorizationDeclinedError
│ ├── XboxAuthError
│ │ └── XSTSError (carries XErr code)
│ │ ├── NoXboxAccountError # 2148916233
│ │ ├── RegionBlockedError # 2148916235
│ │ ├── VerifyAgeRequiredError # 2148916236
│ │ ├── AdultVerificationRequiredError # 2148916237
│ │ └── ChildAccountError # 2148916238 (needs Family Pack)
│ └── MinecraftAuthError
│ └── MinecraftProfileNotFoundError
└── McApiError (REST API failures)
├── HttpError (status_code, body, url)
├── NotFoundError
├── BadRequestError # 400
├── UnauthorizedError # 401
├── ForbiddenError # 403
├── RateLimitedError # 429, carries retry_after
├── InvalidProfileError
├── NameTakenError
├── NameNotAllowedError
└── TooManyNamesError
MCAuthError was an alias of McAuthError in 0.3.x; it was removed in
0.4. Network-level failures (httpx.RequestError, TimeoutError)
propagate unchanged — those aren't this library's domain.
Reusing an httpx.AsyncClient
Every public function accepts an optional http_client= so callers can
plug in custom timeouts, proxies, transport mocks, retry transports,
caching transports, etc:
async with httpx.AsyncClient(timeout=15.0, proxy="http://...") as client:
session = await login_device_code_v1(http_client=client)
profile = await get_own_profile(session, http_client=client)
Retries and HTTP caching
mcapi-auth doesn't bake in a retry or caching layer — they're
httpx-level concerns, so attach them to the client you pass in.
-
httpx-retriesfor exponential-backoff retries:from httpx_retries import Retry, RetryTransport retry = Retry(total=5, backoff_factor=0.5, status_forcelist=[500, 502, 503, 504]) async with httpx.AsyncClient(transport=RetryTransport(retry=retry)) as client: ...
Be conservative with retry counts on the MSA / XSTS / Mojang token endpoints — they're rate-limit-sensitive. Public lookup endpoints (
api.mojang.com) are friendlier; respectRetry-Afteron 429. -
hishelfor RFC 9111 HTTP caching. Mojang's public profile / piston-meta / blocked-servers endpoints returnCache-Controlheaders; wrapping the client in a hishel cache transport gives you transparent revalidation for free. Token-mint endpoints (login.live.com, XBL, XSTS,loginWithXbox) shouldn't be cached — they correctly emit no-store, so they pass through.
Customising the default User-Agent
When you don't pass http_client=, the library builds a fallback
client that sends User-Agent: mcapi-auth/<version>. Override it
process-wide with:
from mcapi_auth import set_default_user_agent, get_default_user_agent
set_default_user_agent("my-app/1.2.3 (+https://example.org/contact)")
print(get_default_user_agent()) # "my-app/1.2.3 (…)"
Caller-supplied clients are never mutated — if you pass your own
httpx.AsyncClient, its headers stay exactly as you configured them.
Blank values are rejected with ValueError.
Cookie-based bulk auth
For unattended automation against accounts you own,
mcapi_auth.auth.cookies ports the three flows that work from a
captured Microsoft session without typing a password:
from mcapi_auth import (
login_with_cookies_msa_v1,
login_with_cookies_sisu,
login_with_cookies_msa_v2_loopback,
CookieAuthError,
BrowserCookie,
)
# Flow 1 — Live-Connect "Java public client": returns MSA access+refresh
tokens = await login_with_cookies_msa_v1("MSPAuth=...; MSPProf=...")
# Flow 2 — SISU (Xbox SSO): returns XBL/XSTS tokens (no refresh available)
sisu = await login_with_cookies_sisu("MSPAuth=...; MSPProf=...")
# Flow 3 — Prism Launcher (Azure-AD consumers): accepts structured cookies
tokens = await login_with_cookies_msa_v2_loopback([
BrowserCookie(name="MSPAuth", value="...", domain=".live.com"),
BrowserCookie(name="MSPProf", value="...", domain=".live.com"),
])
Cookie acquisition is intentionally out of scope — bring your own
Selenium / nodriver / playwright session. See
examples/cookie_login.py for the
"try MSA-v1, fall back to SISU on CookieAuthError" pattern.
⚠️ These primitives let you act as an account using its session cookies. Only use them on accounts you own or have explicit permission to automate.
Beyond login_device_code_v1()
A few additional auth-side helpers:
mcapi_auth.auth.auth_code— authorization-code + PKCE entry point for desktop apps that prefer a localhost redirect over device-code.mcapi_auth.decode_minecraft_access_token(token)— decode the MC JWT offline to readexp/ username / UUID from the embeddedpfdclaim.mcapi_auth.fetch_entitlements(access_token)—/entitlements/mcstore→has_java/has_bedrock/has_game_pass. Distinguishes "doesn't own MC" from "owns Bedrock only" (/minecraft/profile404s in both).mcapi_auth.join_server(...)—sessionserver.mojang.com/session/minecraft/join, for proving profile ownership during a third-party-server handshake.
Long-running apps — AuthChain + Holder
For apps that hold a single account open for hours/days,
mcapi_auth.AuthChain wraps the full MSA → XBL → XSTS → Minecraft
token chain with per-stage lazy refresh and listeners. Each stage is a
Holder[T] that knows how to refresh itself when expired; downstream
holders are invalidated automatically on MSA rotation.
from mcapi_auth import AuthChain, MsaApplicationConfig
# Default: v1 device-code flow with the official MC launcher client_id.
chain = await AuthChain.login()
# For v2 / Azure-AD instead:
# chain = await AuthChain.login(
# flow="device_code_v2", app=MsaApplicationConfig.from_known("prism")
# )
# Persist on every rotation:
chain.on_change(lambda stage, _old, _new: state.save(chain.dump_json()))
while running:
mc = await chain.get_minecraft_token() # refreshes if expired
await do_stuff(mc.access_token)
Restoring across restarts retains XBL+XSTS so you don't re-derive the chain on cold start:
chain = AuthChain.load_json(state.load(), app=MsaApplicationConfig.v1_launcher())
mc = await chain.get_minecraft_token() # uses cached values when fresh
MsaApplicationConfig bundles (client_id, scope, authorize_url, token_url, device_code_url, redirect_uri, xbl_use_d_prefix, is_v1) so
the same config can be threaded through every helper:
MsaApplicationConfig.v2(client_id=...)— modern consumers endpoint.MsaApplicationConfig.v1_launcher(client_id=...)— legacy Live-Connect endpoint, MBI_SSL scope, raw RPS ticket.MsaApplicationConfig.from_known(alias)— resolve an alias ("prism","java","liquidlauncher","bedrock-android", …) into the correctly-shaped v1 or v2 config, with the known redirect override applied.
Realms (Java edition)
from mcapi_auth import (
accept_realms_tos,
fetch_realms_join_info,
fetch_realms_worlds,
is_realms_tos_agreed,
)
if not await is_realms_tos_agreed(session):
await accept_realms_tos(session)
for world in await fetch_realms_worlds(session):
print(world.world_id, world.name, world.owner_username)
info = await fetch_realms_join_info(session, world.world_id)
print(info.host, info.port)
All Realms calls accept any MinecraftSession-like object (anything
exposing access_token + uuid + username), including an
AuthChain.to_session() result. The version= cookie defaults to
mcapi_auth.DEFAULT_REALMS_GAME_VERSION (currently "1.21.4"); pass
game_version="..." to override.
Bedrock realms are not implemented (Bedrock uses a different API and different XSTS relying party).
Proxying a Minecraft client — join_server + server-id hash
For implementing the client side of online-mode authentication (e.g. a Minecraft proxy, a custom auth gateway, or an axochat-style service):
from mcapi_auth import (
compute_server_id_hash,
join_server,
join_server_with_session,
)
# Low-level: you already have a server-id hash
await join_server(session, server_id="abc123...")
# High-level: hand it the raw fields from the Encryption Request packet
await join_server_with_session(
session,
server_id_str=encryption_request.server_id, # ASCII, ≤20 chars, often ""
shared_secret=client_aes_key, # 16-byte AES key the client generated
public_key_der=encryption_request.public_key, # X.509 SubjectPublicKeyInfo blob
)
compute_server_id_hash() is exposed separately for tests / inspection.
It implements the Notchian signed-hex SHA-1 (digest interpreted as a
160-bit two's-complement integer, hex-formatted with no leading zeros).
Debugging a chain — describe_chain / chain_state_summary
from mcapi_auth import describe_chain, chain_state_summary, describe_minecraft_token
print(describe_chain(chain))
# AuthChain client_id=00000000402b5328 v1=True
# msa ✓ 59min (EwAIA...(982 chars))
# xbl · —
# xsts · —
# minecraft ✓ 23.9hr (eyJhbG...(842 chars))
# profile ✓ — (Notch <069a79f444e9...>)
# Machine-readable form for logs / metrics:
for row in chain_state_summary(chain):
log.info("stage", **row.to_dict())
# Peek at the JWT claims of a Minecraft access token:
print(describe_minecraft_token(chain.minecraft_holder.get_cached().access_token))
All helpers are read-only, redact token bodies, and never make network calls.
Multiple accounts — AccountManager
For programs juggling several accounts (chat bridges, alt managers,
multi-account servers), AccountManager stores chains as one JSON
file per account under ~/.local/state/mcapi_auth/accounts/:
from mcapi_auth import AccountManager, AuthChain, MsaApplicationConfig
mgr = AccountManager() # or AccountManager(Path("/var/lib/mybot/accounts"))
# After login, save the chain under a label (the username is a natural choice):
chain = await AuthChain.login(app=MsaApplicationConfig.v2(), prompt=...)
profile = await chain.get_profile()
await mgr.save(profile.username, chain)
# Next run:
print(mgr.list_labels()) # ['Notch', 'jeb_', ...]
chain = await mgr.load("Notch")
mc = await chain.get_minecraft_token()
# Auto-persist on token rotation:
chain.on_change(mgr.make_listener_for("Notch", chain))
# Or restore everything at once:
chains = await mgr.load_all() # dict[str, AuthChain]
Labels must match [A-Za-z0-9._-] and start with an alphanumeric
(rejects .., /, leading dots). Files are written atomically with
0600 permissions. The default directory honours XDG_STATE_HOME.
Player chat-signing certificates (1.19+)
Minecraft 1.19 introduced signed chat (and chat reporting in 1.19.1+);
the client must fetch a Mojang-signed RSA key-pair from
/player/certificates and sign outbound messages with it.
from mcapi_auth import fetch_player_certificates
certs = await fetch_player_certificates(session)
print(certs.expires_at, certs.refreshed_after)
public_der = certs.key_pair.public_key_der() # raw DER bytes
mojang_sig = certs.public_key_signature_v2_bytes # base64-decoded
MinecraftKeyPair.public_key / private_key are PEM strings;
.public_key_der() / .private_key_der() strip the PEM armor and
base64-decode for you. No cryptography dependency — load the keys
with your preferred crypto library if you need to sign.
PlayFab login (Bedrock telemetry)
Minecraft: Bedrock Edition logs into PlayFab in addition to Xbox Live, using an XSTS token. Once authenticated you get a PlayFab entity token (short-lived JWT used by the title service), a stable PlayFab account id, and a long-lived session ticket.
from mcapi_auth import (
BEDROCK_PLAYFAB_TITLE_ID,
playfab_get_entity_token,
playfab_login_with_xbox,
)
# `xsts` here is an mcapi_auth.XSTSToken — for PlayFab you usually
# want an XSTS issued against rp `http://playfab.xboxlive.com/`,
# which differs from the Minecraft RP. Get it however you like; this
# function only consumes the token.
pf = await playfab_login_with_xbox(xsts, title_id=BEDROCK_PLAYFAB_TITLE_ID)
print(pf.play_fab_id, pf.session_ticket, pf.entity_token.expires_at)
# Refresh just the entity token later, no XSTS round-trip needed:
new_entity = await playfab_get_entity_token(pf.entity_token)
This module covers the PlayFab piece only — see the Bedrock section below for the rest of the client chain.
Bedrock Edition client chain
Optional, requires the [bedrock] extra (which pulls in
cryptography>=43 for the ES384 keypair):
pip install mcapi-auth[bedrock]
Once an XSTS token scoped to Bedrock's relying party
(https://multiplayer.minecraft.net/) and a PlayFab session ticket
are in hand, you can run the rest of the chain:
from mcapi_auth.api.bedrock import (
generate_bedrock_session_keypair,
minecraft_authenticate,
start_minecraft_session,
start_minecraft_multiplayer_session,
)
from uuid import uuid4
key_pair = generate_bedrock_session_keypair() # ES384 / P-384
chain = await minecraft_authenticate(bedrock_xsts, key_pair)
print(chain.xuid, chain.display_name, chain.expires_at)
session = await start_minecraft_session(
pf.session_ticket,
game_version="1.21.50",
device_id=uuid4(),
)
mp = await start_minecraft_multiplayer_session(session, key_pair)
print(mp.xuid, mp.uuid, mp.token)
The ES384 keypair should be persisted across launches — Mojang binds
it to the player's account in the identityJwt. Use
BedrockKeyPair.to_pem() / BedrockKeyPair.from_pem() for storage.
Note:
mcapi_auth's built-inauthenticate_xsts()is scoped to the Java relying party. For a Bedrock-scoped XSTS use the Sisu flow inmcapi_auth.auth.xbox_device(added in 0.12.0) — it returns a UserToken, TitleToken, and an XSTSToken in one call, all bound to a persistent device keypair. Seeexamples/bedrock_minimal.py.
Sisu flow / device-token authentication
For Bedrock and other Microsoft title client ids, the plain
user.auth.xboxlive.com + xsts.auth.xboxlive.com chain is
insufficient — you need a TitleToken as well, which only the Sisu
endpoint mints. The mcapi_auth.auth.xbox_device module wraps it:
from mcapi_auth import BEDROCK_WIN32_CLIENT_ID
from mcapi_auth.auth.xbox_device import (
XBL_XSTS_BEDROCK_RELYING_PARTY,
XblDeviceKeyPair,
authenticate_xbl_device,
sisu_authorize,
)
from uuid import uuid4
# Persist these across launches; Xbox treats them as a device identity.
device_kp = XblDeviceKeyPair.generate()
device_id = uuid4()
device_token = await authenticate_xbl_device(device_kp, device_id=device_id)
sisu = await sisu_authorize(
msa.access_token,
device_token,
device_kp,
client_id=BEDROCK_WIN32_CLIENT_ID,
relying_party=XBL_XSTS_BEDROCK_RELYING_PARTY,
)
print(sisu.xsts_token.token, sisu.user_token.userhash, sisu.title_token.title_id)
The returned sisu.xsts_token is shape-compatible with
mcapi_auth.XSTSToken (same .token / .userhash attributes)
and can be passed straight to minecraft_authenticate,
playfab_login_with_xbox, or any of the other XSTS-consuming helpers.
Requires the [bedrock] extra (for cryptography).
BedrockAuthManager: full chain with lazy refresh
For long-running clients, BedrockAuthManager (added in 0.13.0) is
the Bedrock equivalent of AuthChain — it owns the stable Xbox
identity (device keypair + UUID + ES384 client keypair) and every
downstream token (MSA, DeviceToken, the two Sisu legs, PlayFab,
certificate chain, franchise session, multiplayer token), each in a
Holder that refreshes on demand:
from mcapi_auth.auth.bedrock_chain import BedrockAuthManager
mgr = await BedrockAuthManager.login()
mgr.on_change(lambda *_: state.save(mgr.dump_json()))
while running:
mp = await mgr.get_multiplayer_token() # auto-refreshes
await join_server(mp.token)
# later, in another process:
mgr = BedrockAuthManager.load_json(state.load())
cert = await mgr.get_certificate_chain()
BedrockAuthManager.login() accepts both v1 and v2 client_ids. By
default it builds a MsaApplicationConfig.v1_launcher(client_id= bedrock_client_id) and threads the matching device_code_url /
token_url / scope through the MSA layer — so every Bedrock
client_id (Win32, Android, iOS, Nintendo, PlayStation), which is only
registered against Microsoft's legacy login.live.com/oauth20_*.srf
endpoints, works without an explicit config.
Bootstrap shortcut: the Bedrock-Win32 client_id is registered against a custom-protocol redirect that browsers can't follow, so for a first-time browser-driven bootstrap you can drive the MSA leg with the Java launcher's client_id (
MINECRAFT_LAUNCHER_V1_CLIENT_ID) — XBL entitlement is keyed off the resulting Xbox profile, not off the MSA client_id — and passbedrock_client_id=BEDROCK_WIN32_CLIENT_IDtoBedrockAuthManager.from_msa(...)so the rest of the chain still targets the Bedrock relying party. The refreshed snapshot stores the Bedrock client_id and uses it on subsequent refreshes.
Persistence keeps the device keypair + UUID stable across runs (Xbox remembers them as a single device identity), and only the stages whose inputs actually changed are invalidated on refresh — e.g. an MSA rotation re-runs the Sisu legs but keeps the DeviceToken.
More examples
See examples/ for runnable scripts covering each entry
point: device-code, browser-driven, refresh-token reuse, cookie-based
bulk auth, custom storage, manual auth-code integration, entitlements,
joinServer, and offline JWT decode.
Development
uv sync
uv run pytest
uv run ruff check .
uv run basedpyright
Why not msal?
Microsoft's official library is ~7 MB of code that mostly handles
enterprise tenants we don't need. The device-code flow is ~50 lines
hand-rolled with httpx — see src/mcapi_auth/auth/msa.py.
Client-ID disclaimer
By default we use the public Minecraft Launcher client_id
(00000000-402b-4cd3-a82b-c45ab2f1d3f7) that every open-source launcher
relies on. Microsoft has tolerated this for ~5 years; if they ever
revoke it, every Minecraft launcher on Earth breaks the same day. Pass
a different client_id= to login_device_code_v1() if you have your own MSA app
registration.
Known client_id catalog
mcapi_auth.KNOWN_CLIENT_IDS maps friendly aliases to well-known
Microsoft client_ids used across the Minecraft ecosystem. v1 (16-hex,
no dashes) IDs work against login.live.com/oauth20_*.srf with the
MBI_SSL scope; v2 (Azure-AD GUID) IDs work against
login.microsoftonline.com/consumers/oauth2/v2.0/* with
XboxLive.signin offline_access.
The matrix below is what each client_id actually accepts as a
redirect_uri, as derived from probing every entry end-to-end against
the v1 and v2 authorize endpoints. Use the listed flow:
| alias | type | accepted redirect_uri(s) | flow |
|---|---|---|---|
java |
v1 | OOB only (oauth20_desktop.srf) |
login_browser_v1 |
bedrock-android |
v1 | OOB only | login_browser_v1 |
bedrock-ios |
v1 | OOB only | login_browser_v1 |
bedrock-nintendo |
v1 | OOB only | login_browser_v1 |
bedrock-playstation |
v1 | OOB only | login_browser_v1 |
bedrock-win32 |
v1 | broken upstream for OOB. Use java / MINECRAFT_LAUNCHER_V1_CLIENT_ID for the MSA leg and bedrock_client_id=BEDROCK_WIN32_CLIENT_ID on BedrockAuthManager — XBL entitlement keys off the resulting Xbox profile, not the MSA client_id. |
(MSA via java) |
xbox-app-ios |
v1 | OOB only | login_browser_v1 |
xbox-gamepass-ios |
v1 | OOB only | login_browser_v1 |
prism (default) |
v2 | http://{127.0.0.1,localhost}:*/ (root path) |
login_browser_v2 or login_device_code_v2 |
liquidlauncher/liquidbounce |
v2 | http://localhost:*/login |
login_browser_v2 or login_device_code_v2 |
edu |
v2 | none — no loopback registered | login_device_code_v1 only |
office365 |
v2 | none — no loopback registered | login_device_code_v1 only |
Helpers:
is_v1_client_id(client_id)— decide between v1/v2 endpoint families.resolve_client_id(name_or_id)— alias → client_id lookup.resolve_browser_redirect(client_id)— returns(bind_host, redirect_path)for clients with a known registered loopback URI (currentlyprism,liquidlauncher);Noneotherwise.is_browser_unsupported(client_id)—Trueiflogin_browser_v2(v2 loopback) cannot succeed for this client_id: every v1 ID (rejected by the v2 endpoint asAADSTS70001) plus every v2 ID without a loopback URL registered (edu,office365).
License
MIT. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcapi_auth-0.19.3.tar.gz.
File metadata
- Download URL: mcapi_auth-0.19.3.tar.gz
- Upload date:
- Size: 257.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d66715668dfda5773abe41722bca839353092cfdb2755e4ef242eccc4847285d
|
|
| MD5 |
73fe0fdb51e4beca174c2f83cabdc5a8
|
|
| BLAKE2b-256 |
93173e80613505c46939f2c8e389ba22b778c691ec81396d11279ecf77db45f1
|
File details
Details for the file mcapi_auth-0.19.3-py3-none-any.whl.
File metadata
- Download URL: mcapi_auth-0.19.3-py3-none-any.whl
- Upload date:
- Size: 130.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7d28b684f2df9d8b914738fb08e9e0107c6b54506692a20e8c744609d96a2870
|
|
| MD5 |
9439806a03b5ec801e55328930fb9198
|
|
| BLAKE2b-256 |
4ca6d76357209585a1c589ee1c149dfa70d3d0be8ed2b67d0ba17e75ce978a37
|