MCAuth 1.0.2

dotnet add package MCAuth --version 1.0.2
                    
NuGet\Install-Package MCAuth -Version 1.0.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MCAuth" Version="1.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MCAuth" Version="1.0.2" />
                    
Directory.Packages.props
<PackageReference Include="MCAuth" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add MCAuth --version 1.0.2
                    
#r "nuget: MCAuth, 1.0.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package MCAuth@1.0.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=MCAuth&version=1.0.2
                    
Install as a Cake Addin
#tool nuget:?package=MCAuth&version=1.0.2
                    
Install as a Cake Tool

MCAuth

A library for web apps to authenticate via the user's Minecraft account. A code from Microsoft's login flow must be obtained first, which this library also helps with generating a URL to redirect to. After a successful login through Microsoft you will then receive a code, which you can then pass to this library to complete the process.

Background

In order to authenticate via a Minecraft account many HTTP requests must be made, this library aims to simplify the process by doing it all for you. Here is a detailed description of each request made behind the scenes during authentication:

  • Microsoft token (requires code from Microsoft login flow)
  • Xbox Live token (requires Microsoft token from previous step)
  • Xbox Live XSTS token (requires Xbox Live token from previous step)
  • Minecraft Token (requires both Xbox Live and XSTS token from previous steps)
  • Minecraft Profile (requires Minecraft token from previous step)

Usage

Authenticating with this library is a three-step process.

Step 1 - Microsoft Login Flow

You will need to log in through Microsoft's login flow, which must be done with a specific url that can be generated with this library like so:

var client = new MCAuthClient("AZURE_CLIENT_ID", "AZURE_CLIENT_SECRET");
var redirectUrl = "https://my-app.com/login";
var url = client.GetMicrosoftLoginUrl(redirectUrl);

If you are using an ASP.NET API, you can easily redirect a user to this url in a controller like so:

[ApiController]
[Route("/api/[controller]/[action]")]
public class UserController : ControllerBase
{
  [HttpGet] 
  public IActionResult Login()
  {
    var client = new MCAuthClient("AZURE_CLIENT_ID", "AZURE_CLIENT_SECRET");
    var redirectUrl = "https://my-app.com/login";
    var url = client.GetMicrosoftLoginUrl(redirectUrl);

    return Redirect(url);
  }
}

Step 2 - Authentication

After you have successfully logged in, you will be redirected to the url you provided along with a code query parameter. With our example, the url would look something like this: https://my-app.com/login?code=M.C503_AB1.2.U.01234567-89ab-cdef-0123-456789abcdef. Use this code for the Authenticate method:

var client = new MCAuthClient("AZURE_CLIENT_ID", "AZURE_CLIENT_SECRET");
var code = "M.C503_AB1.2.U.01234567-89ab-cdef-0123-456789abcdef"; // retrieved from the previous step
var redirectUrl = "https://my-app.com/login"; // it's important that this is the same url used for the login flow
var result = await client.Authenticate(new MCAuthRequest(code, redirectUrl), cancellationToken);

The result contains the HTTP responses from each service mentioned earlier.

Step 3 - Additional Token (Optional)

You may want to create your own additional token that you will use to authenticate with your app. The reason you might need this is that you likely will have your own user ID/GUID in a database which is tied to your Minecraft ID and username. Although, if you choose to only store your Minecraft ID in your database then you may be able to skip this step and instead authenticate directly with the Minecraft access token returned from Authenticate. If you do choose to create your own token, our library also has a method on the result to help during this process:

// retrieve your userId any way you'd like, but it'll most likely be by Minecraft ID
var userId = await _userRepository.GetByMinecraftId(result.MinecraftProfile.Id);

var token = result.CreateToken(new MCAuthTokenOptions("JWT_SECRET", new DateTimeDuration { Days = 1 }) {
  ExtraClaims = new List<Claim> {
    new(ClaimTypes.Name, userId.ToString())
    // these claims are added by default, but are customizable if needed
    // new(ClaimTypes.NameIdentifier, result.MinecraftProfile.Id);
    // new(ClaimTypes.GivenName, result.MinecraftProfile.Name);
  }
});

Again, if you are using an ASP.NET API, a full solution might look something like this:

[ApiController]
[Route("/api/[controller]/[action]")]
public class UserController : ControllerBase
{
  // you probably want to retrieve the ClientId and ClientSecret with environment variables
  private readonly MCAuthClient _client = new MCAuthClient("AZURE_CLIENT_ID", "AZURE_CLIENT_SECRET");
  private readonly string _redirectUrl = "https://my-app.com/login";
  
  private readonly IUserRepository _userRepository;
  
  public UserController(IUserRepository userRepository)
  {
    _userRepository = userRepository;
  }
  
  [HttpGet]
  public IActionResult Login()
  {
    var url = _client.GetMicrosoftLoginUrl(_redirectUrl);

    return Redirect(url);
  }
  
  // capture the `code` query parameter on your front end and then provide it here
  [HttpPost]
  public async Task<IActionResult> Authenticate([FromQuery] string code, CancellationToken cancellationToken)
  {
    var result = await _client.Authenticate(new MCAuthRequest(code, _redirectUrl), cancellationToken);
    
    // retrieve your userId any way you'd like, but it'll most likely be by Minecraft ID
    var userId = await _userRepository.GetByMinecraftId(result.MinecraftProfile.Id);

    var token = result.CreateToken(new MCAuthTokenOptions("JWT_SECRET", new DateTimeDuration { Days = 1 }) {
      ExtraClaims = new List<Claim> {
        new(ClaimTypes.Name, userId.ToString())
        // these claims are added by default, but are customizable if needed
        // new(ClaimTypes.NameIdentifier, result.MinecraftProfile.Id);
        // new(ClaimTypes.GivenName, result.MinecraftProfile.Name);
      }
    });

    return Ok(result);
  }
}

Events

You also have the ability to capture HTTP requests, responses, and errors that occur in the Authenticate method while it is still executing for each of the services that are interacted with. Each event has both synchronous and asynchronous support. Capturing errors in events may be trivial in most cases since an exception is thrown by the library immediately after your error event, but if you needed to execute something before that exception is thrown you can do so.

Here are a few example use cases:

Logging

var serializerOptions = new JsonSerializerOptions { WriteIndented = true };
var logEvent = (string message, object obj, LogLevel logLevel = LogLevel.Information) => {
  _Logger.Log(logLevel, $"{message}: {{0}}", JsonSerializer.Serialize(obj, serializerOptions));
};

var result = await _client.Authenticate(new MCAuthRequest(code, _redirectUrl) {
  Options = new MCAuthOptions {
    MicrosoftTokenEvents = new MicrosoftAuthTokenEvents {
      OnRequest = request => logEvent("MicrosoftToken Request", request),
      OnResponse = response => logEvent("MicrosoftToken Response", response),
      OnError = error => logEvent("MicrosoftToken Error", error, LogLevel.Error)
    },
    XboxLiveTokenEvents = new XboxLiveAuthTokenEvents {
      OnRequest = request => logEvent("XboxLive Request", request),
      OnResponse = response => logEvent("XboxLive Response", response),
      OnError = error => logEvent("XboxLive Error", error, LogLevel.Error)
    },
    XboxLiveXstsTokenEvents = new XboxLiveXstsAuthTokenEvents {
      OnRequest = request => logEvent("XboxLiveXSTS Request", request),
      OnResponse = response => logEvent("XboxLiveXSTS Response", response),
      OnError = error => logEvent("XboxLiveXSTS Error", error, LogLevel.Error)
    },
    MinecraftTokenEvents = new MinecraftAuthTokenEvents {
      OnRequest = request => logEvent("MinecraftToken Request", request),
      OnResponse = response => logEvent("MinecraftToken Response", response),
      OnError = error => logEvent("MinecraftToken Error", error, LogLevel.Error)
    },
    MinecraftProfileEvents = new MinecraftProfileAuthEvents {
      OnRequest = request => logEvent("MinecraftProfile Request", request),
      OnResponse = response => logEvent("MinecraftProfile Response", response),
      OnError = error => logEvent("MinecraftProfile Error", error, LogLevel.Error)
    }
  }
}, cancellationToken);

Client Messages (SignalR)

var serializerOptions = new JsonSerializerOptions { WriteIndented = true };
var sendClientMessage = async (string message, object obj) => {
  await _userHub.SendMessage(string.Format($"{message}: {{0}}", JsonSerializer.Serialize(obj, serializerOptions)));
};

var result = await _client.Authenticate(new MCAuthRequest(code, _redirectUrl) {
  Options = new MCAuthOptions {
    MicrosoftTokenEvents = new MicrosoftAuthTokenEvents {
      OnRequest = async request => await sendClientMessage("MicrosoftToken Request", request),
      OnResponse = async response => await sendClientMessage("MicrosoftToken Response", response),
      OnError = async error => await sendClientMessage("MicrosoftToken Error", error)
    },
    XboxLiveTokenEvents = new XboxLiveAuthTokenEvents {
      OnRequest = async request => await sendClientMessage("XboxLive Request", request),
      OnResponse = async response => await sendClientMessage("XboxLive Response", response),
      OnError = async error => await sendClientMessage("XboxLive Error", error)
    },
    XboxLiveXstsTokenEvents = new XboxLiveXstsAuthTokenEvents {
      OnRequest = async request => await sendClientMessage("XboxLiveXSTS Request", request),
      OnResponse = async response => await sendClientMessage("XboxLiveXSTS Response", response),
      OnError = async error => await sendClientMessage("XboxLiveXSTS Error", error)
    },
    MinecraftTokenEvents = new MinecraftAuthTokenEvents {
      OnRequest = async request => await sendClientMessage("MinecraftToken Request", request),
      OnResponse = async response => await sendClientMessage("MinecraftToken Response", response),
      OnError = async error => await sendClientMessage("MinecraftToken Error", error)
    },
    MinecraftProfileEvents = new MinecraftProfileAuthEvents {
      OnRequest = async request => await sendClientMessage("MinecraftProfile Request", request),
      OnResponse = async response => await sendClientMessage("MinecraftProfile Response", response),
      OnError = async error => await sendClientMessage("MinecraftProfile Error", error)
    }
  }
}, cancellationToken);

Exceptions

  • MCAuthException - Occurs when an HTTP response contains an error message in the response body. Contains a HttpStatusCode property. Each service has its own exception which extends from this base exception, each with custom fields which match fields from the response body for that service:
    • MicrosoftAuthException - Contains Error, ErrorDescription, and CorrelationId properties which are populated from JSON response body. Message shows details of each.
    • XboxLiveAuthException - Contains no extra properties. Message is populated directly from plain text response body.
    • XboxLiveXstsAuthException - Contains Identity, XErr, ErrorMessage, and Redirect properties which are populated from JSON response body. Message show details of each.
    • MinecraftAuthException - Contains no extra properties. Message is populated directly from plain text response body.
    • MinecraftProfileAuthException - Contains Path, ErrorType, Error, ErrorMessage, and DeveloperMessage properties which are populated from JSON response body. Message shows details of each.
  • HttpRequestException - Occurs when an HTTP request could not be made to the service. Usually because it's offline.
  • TimeoutException - Occurs when an HTTP request times out on the service. Most likely if the service is experiencing a heavy load or large number of requests.

Known Error Codes

Microsoft Token

Reference: Redeem a code for an access token

Error Description
consent_required The request requires user consent. This error is non-standard. It's usually only returned on the /authorize endpoint per OIDC specifications. Returned when a scope parameter was used on the code redemption flow that the client app doesn't have permission to request.
interaction_required Non-standard, as the OIDC specification calls for this code only on the /authorize endpoint. The request requires user interaction. For example, another authentication step is required.
invalid_client Client authentication failed.
invalid_grant The authorization code or PKCE code verifier is invalid or has expired.
invalid_request Protocol error, such as a missing required parameter.
invalid_resource The target resource is invalid because it doesn't exist, Microsoft Entra ID can't find it, or it's not correctly configured.
invalid_scope The scope requested by the app is invalid.
temporarily_unavailable The server is temporarily too busy to handle the request.
unauthorized_client The authenticated client isn't authorized to use this authorization grant type.
unsupported_grant_type The authorization server doesn't support the authorization grant type.

Xbox Live XSTS

Reference: Obtain XSTS token for Minecraft

XErr Description
2148916227 The account is banned from Xbox.
2148916233 The account does not have an Xbox account. Please sign up or login to minecraft.net first.
2148916235 The account is from a country where Xbox Live is not available/banned.
2148916236 The account needs adult verification on Xbox page. (South Korea)
2148916237 The account needs age verification on Xbox page. (South Korea)
2148916238 The account is a child and cannot proceed unless the account is added to a Family by an adult.
2148916262 TBD, happens rarely without any additional information.

Minecraft Profile

Reference: Getting the Profile

Error Description
NOT_FOUND Minecraft is not owned on this account. If you are an Xbox Game Pass user you must log into the Minecraft Launcher at least once first.

Testing

See MCAuth.Testing library.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on MCAuth:

Package Downloads
MCAuth.Testing

The testing library is used for testing purposes only. It automatically mocks HTTP requests made by the library and returns a custom response provided by you.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.2 34 2/19/2026

Initial 1.0.0 release