Back to home
C#OAuth 2.0Security

Secure Microsoft account sign-in in a desktop app

Hazar Akbuz · · 2 min read · Updated

How we added Microsoft account sign-in to Projects Launcher: PKCE, a short-lived loopback listener and a session stored with DPAPI.

Projects Launcher is an open-source Minecraft launcher we build as the projects.gg team (C#, .NET Framework 4.7.2). So that players can join servers in online mode with the account they actually bought, we added Microsoft account sign-in to the launcher. The whole flow lives in a single folder and needs no extra NuGet dependency.

A five-link chain

  1. Microsoft, OAuth 2.0 + PKCE: the user signs in on Microsoft's own page; the launcher only receives the authorisation code.
  2. Xbox Live: the Microsoft token is exchanged for an Xbox Live identity.
  3. XSTS: the Xbox Live identity is used to obtain an authorisation token.
  4. Minecraft Services: the XSTS token is exchanged for the game's own session token.
  5. Profile: the account's Minecraft profile is read and the game starts with that session.

Responsibilities are split across four files: the chain itself (MicrosoftAuth.cs), the layer that stores the session and refreshes expired tokens (PremiumSession.cs), the sign-in window with progress steps, the licence warning and errors (PremiumLoginForm.cs), and a small class that draws the Microsoft logo without needing an image file (MicrosoftBrand.cs).

A launcher that never sees the password

The authorisation code is captured by a short-lived loopback listener on a random free port. The user signs in in their own browser, on Microsoft's real page, so the launcher never sees the password at any point. PKCE means that even someone who intercepts the code cannot exchange it for a token on their own.

Storing the session: DPAPI

The Microsoft refresh token is stored at %APPDATA%\.projects\premium.dat, encrypted with Windows DPAPI in the CurrentUser scope. Copied to another user account or another machine, the file is useless.

If you fork the project

Every fork needs its own Azure application. In the Azure portal, under App registrations → New registration, choose personal Microsoft accounts only as the supported account type, set the redirect URI to http://localhost on the Public client/native platform, turn on Allow public client flows and copy the application ID into MicrosoftAuth.ClientId. No API permission needs to be added in the portal: the XboxLive.signin offline_access scope is requested at sign-in time. Client IDs are public values, not secrets.

Source code and details: github.com/projects-gg/MinecraftLauncher