Skip to content

Major Rewrite (WIP)#2

Draft
lactyy wants to merge 75 commits intodf-mc:mainfrom
lactyy:rewrite
Draft

Major Rewrite (WIP)#2
lactyy wants to merge 75 commits intodf-mc:mainfrom
lactyy:rewrite

Conversation

@lactyy
Copy link
Collaborator

@lactyy lactyy commented Feb 19, 2026

This pull request rewrites the go-xsapi library to make it more usable in many use cases, with authentication support.

Authentication

The xsapi/xal/sisu package provides a way to authenticate and authorize with Xbox Live services using a MSA (Microsoft Account) OAuth2 token.
It also efficiently requests XSTS tokens by using caches and individual endpoints instead of using sisu.xboxlive.com/authorize used in Gophertunnel.

// Notify for Ctrl+C and other interrupt signals so the user can abort
// the device authorization flow or other operations at any time.
signals, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill)
defer cancel()

// Use the Device Authorization Flow to sign in to a Microsoft Account.
da, err := MinecraftAndroid.DeviceAuth(signals)
if err != nil {
	panic(fmt.Sprintf("error requesting device authorization flow: %s", err))
}

_, _ = fmt.Fprintf(os.Stderr, "Sign in to your Microsoft Account at %s using the code %s.", da.VerificationURI, da.UserCode)

// Make a context for polling the access token while the user completes sign-in.
// In this case, we allow one minute to complete login (you may configure a longer timeout).
pollCtx, cancel := context.WithTimeout(signals, time.Minute)
defer cancel()
token, err := MinecraftAndroid.DeviceAccessToken(pollCtx, da)
if err != nil {
	panic(fmt.Sprintf("error polling access token in device authorization flow: %s", err))
}
// Use TokenSource so we can always use a fresh token.
// This is similar to [auth.RefreshTokenSource] in Gophertunnel.
msa := MinecraftAndroid.TokenSource(context.Background(), token)

// Make a SISU (sisu.xboxlive.com) session using the Microsoft Account token source.
session := MinecraftAndroid.New(msa, nil)

API

The xsapi.Client exposes many clients for each Xbox Live endpoint.
You can create a client as follows:

// Log in to Xbox Live services using the SISU session.
client, err := NewClient(session, nil)
if err != nil {
	panic(fmt.Sprintf("error logging in to Xbox Live: %s", err))
}

client.MPSD() // *mpsd.Client
client.Social() // *social.Client

Multiplayer Session Directory (MPSD)

The xsapi/mpsd package provides a way to publish, discover, and join Xbox Live multiplayer sessions.

// Publish a peer-to-peer multiplayer session for Minecraft: Bedrock Edition.
s, err := client.MPSD().Publish(context.TODO(), mpsd.SessionReference{
	// ServiceConfigID uniquely identifies the game across platforms.
	// For Minecraft: Bedrock Edition, it is 4fc10100-5f7a-4470-899b-280835760c07.
	ServiceConfigID: serviceConfigID,

	// "MinecraftLobby" is the template used for peer-to-peer sessions
	// (also known as Friend Worlds).
	TemplateName: "MinecraftLobby",

	// Name uniquely identifies the multiplayer session.
	// Typically a randomly generated uppercase UUID.
	// Publish() generates one automatically if omitted.
	// Name: strings.ToUpper(uuid.NewString())
}, mpsd.PublishConfig{
	CustomProperties: properties,
})
defer s.Close()

s.Properties() // mpsd.SessionProperties
s.Constants()  // mpsd.SessionConstants

members := s.Members()
member, ok := s.MemberByXUID("xuid") // Find a member by XUID.
member, ok := s.Member("me")         // Find a member by label (e.g. "me", 1, 2, 3).

// Search for open multiplayer sessions.
activities, err := client.MPSD().Activities(context.TODO(), serviceConfigID)
if err != nil {
	panic(err)
}
if len(activities) == 0 {
	panic("no friends are hosting multiplayer sessions")
}
// Join the first multiplayer session we've got from the response.
activity := activities[0]
s, err := client.MPSD().Join(context.TODO(), activity, mpsd.JoinConfig{})
if err != nil {
	panic(err)
}
defer s.Close()

// Custom properties contains title-specific metadata in JSON format.
// For Minecraft peer-to-peer sessions, it includes supported connection methods,
// transport layers, subtypes (such as Signaling over WebSocket or JSON-RPC),
// and addresses/identifiers required to connect.
s.Properties().Custom // json.RawMessage

Social

The xsapi/social package makes use of several endpoints to provide user profiles and relationship management in Xbox Live.

// Search for users by query.
users, err := client.Social().Search(context.TODO(), "Lactyy")
if err != nil {
	panic(err)
}
if len(users) == 0 {
	panic("users not found")
}
user := users[0]
fmt.Println(user.GamerTag) // "Lactyy"

// Send a friend request using the XUID.
if err := client.Social().AddFriend(context.TODO(), user.XUID); err != nil {
	panic(err)
}
_ = client.Social().RemoveFriend(context.TODO(), user.XUID) // :(

// List all friends of the caller (current-authenticated user).
friends, err := client.Social().Friends(context.TODO())
if err != nil {
	panic(err)
}
fmt.Println(len(friends), "friends") // 0 friends

// Subscribe to real-time notifications when someone adds or removes you.
client.Social().Subscribe(context.TODO(), handler)

Game-specific endpoints

Game-specific endpoints that require Xbox Live authentication (such as Minecraft Realms), can also be accessed through xsapi.Client.

// List all Realms joined by the authenticated user.
req, err := http.NewRequest(http.MethodGet, "https://bedrock.frontendlegacy.realms.minecraft-services.net/worlds", nil)
if err != nil {
	panic(err)
}
req.Header.Set("User-Agent", "libhttpclient/1.0.0.0")

// HTTPClient automatically resolves the relying party,
// requests an XSTS token based on remote configuration provided by Xbox Live,
// and sets the Authorization header.
resp, err := client.HTTPClient().Do(req)
if err != nil {
	panic(err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
	panic(fmt.Sprint(resp.Status, resp.StatusCode))
}
var result struct {
	Servers []Realm `json:"servers"`
}
err := json.NewDecoder(resp.Body).Decode(&result)
// Resolve an XSTS token for a specific relying party derived from the request URL.
xsts, _, err := client.TokenAndSignature(context.TODO(), &url.URL{
	Scheme: "https",
	Host:   "20ca2.playfabapi.com",
})
if err != nil {
	panic(err)
}
fmt.Println(xsts.String()) // "XBL3.0 x=...;..."

@lactyy lactyy marked this pull request as draft February 19, 2026 13:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants