Repository navigation
login
Xodus uses InlineLogin.srf, the same hosted login page Windows loads inside CloudExperienceHost (the native shell that embeds sign-in webviews for TokenBroker). It's similar to InlineConnect.srf known from mobile devices, but the page talks to its host over a JS IPC bridge instead of redirect URLs.
The end goal is the same - get the STS token, allowing to get tokens for any supported Microsoft service.
Flow looks as follows
- Open
InlineLogin.srfin a webview, presenting asCloudExperienceHost - The page calls back over IPC as it loads, and again once
post.srffinishes loading, handing over the signed-in user's tokens (DAProperty) - use RST2.srf to exchange it for real Xbox Live tokens (
exchange_user_token) - On SSO failure - open the URL returned in the fault for auth approval
- Call RST2.srf again once that second session completes
On Windows, CloudExperienceHost hosts the login page and exposes itself to it as window.external, plus a CloudExperienceHost.Bridge.dispatchMessage bridge the page can call into and get answers from. Xodus doesn't have a real CloudExperienceHost - xodus-cli/src/webview.rs re-implements just enough of it inside its own embedded webview (tao/wry) for the page to behave as if it were signing in through Windows.
What that involves:
-
Identifying as the host. The initial request to
InlineLogin.srfcarries a set ofcxh-*headers (capabilities, correlation id, MSA/identity client binary versions, OS version, platform, protocol) that a realCloudExperienceHostwould send. Without these the page can behave differently or refuse to proceed. -
Aliasing the IPC channel. wry only exposes
window.ipc.postMessage; an injected init script aliaseswindow.external.notifyto it so the page's existing calls reach Xodus unmodified. -
Two kinds of IPC message. Everything the page posts over IPC lands in
with_ipc_handlerand is tried as two different shapes:- A
DAPropertypayload - the actual sign-in result (DA token, DA session key, STS inline flow token, sign-in name, PUID). This is whatSessionHandler::on_tokenreceives. - A
HostBridgeMessageinvokingCloudExperienceHost.getContext- the page asking its host for context about itself. Xodus answers by evaluating a script that callsdispatchMessageback into the page with a canned context payload, mirroring what the real host would return.
- A
-
Forcing the final handoff. The page only pushes its
ServerData(containing theDAProperty) over IPC on its own if a real host asked for it earlier in a way Xodus doesn't replicate. Instead, once the page finishes loadinghttps://login.live.com/ppsecure/post.srf, Xodus evaluateswindow.ipc.postMessage(JSON.stringify(ServerData))itself to pull the tokens out.
The webview runtime itself is generic: a SessionHandler trait (bootstrap / on_token / on_closed) describes what to do at each step, and a RuntimeCommands action queue lets a handler open or close webview sessions without owning the event loop directly. xodus-cli/src/commands/login.rs's LoginHandler is the only implementation today - its on_token calls exchange_user_token (see RST2.srf), and if that comes back as a SOAP fault with an inline auth URL, it closes the current session and opens a second one at that URL instead of failing outright. Once that second session also produces a DAProperty, the exchange is retried with an extra http://Passport.NET/tb scope added, which is what actually finalizes the token.
If you know about Xbox services, this is similar to XSTS endpoint. It applies to both user and device STS tokens.
You can see a sample RST2.srf request when we used it in device STS flow.
Device token always revolves arround user token - its binary secret is used for signing XML payloads as well as decrypting responses.