Decentralized Auth

Discord Matrix GitLab Modrinth

Decentralized Auth is an alternative authentication system for Minecraft client or server implementations.

With Decentralized Auth, player identity is tied to a cryptographic keypair so that no Mojang or Microsoft API calls are ever required on either the client or server.

Use cases

  • Exercise your power against chat signing and any future anti-features that Microsoft may release in connection with authentication services
  • Continue to use the official Minecraft client after an unfair account ban
  • Host a private server among friends without enforcing strict chat moderation policies
  • Implement custom composable whitelist-based authentication logic on your server's website (2FA, account recovery, etc.)
  • Prevent Microsoft from gathering data about the servers you join
  • No more restarting your client because your auth session has expired

Features

  • Cross-compatibility - users authenticated with Microsoft can play together on the same server as Decentralized Auth users simultaneously
  • Full profile data - Share your skin texture (including your own custom cape!) and profile name to other players without a third-party endpoint
  • It's not just offline mode - all packets are E2E encrypted and your account cannot be stolen by logging in with your name

Motivation

Many of Minecraft's oldest players purchased the game to be a part of its vibrant community. This was a community which grew around the freedom provided by Mojang. Freedom to play however you wanted, freedom to build however you wanted, freedom to mod the game however you wanted, and most importantly the freedom to share all of that with your friends by running your own server however you wanted.

Turns for the worse

In 2014, Mojang released an updated End User License Agreement for Minecraft. This EULA prevented servers from offering any advantages whatsoever in exchange for real-world currency. The change removed a significant source of income for many server administrators, many of whom could no longer afford to operate their servers and had to shut them down. This was a devastating blow to the community. Yet, some server owners adapted and continued to operate under the more restrictive rules, despite the difficulties involved.

Microsoft's acquisition

Microsoft acquired Mojang later in 2014 and begun fracturing the playerbase further with a heavy development focus and subsequent pushing of players towards Minecraft Bedrock Edition.

Not only is Bedrock a completely separate platform that is incompatible with the original game (since dubbed the Java Edition), but it's much less open to modding.

Modding has been an essential part of Minecraft's popularity, truly allowing players to do anything they could imagine. When Bedrock Edition 1.0.0 was officially released in 2016, Minecraft had already built up a tremendous modding community in terms of developers, modpack creators, and users. None of those efforts can be transferred to Bedrock Edition, which built in C++, a foundation that has proven much harder for mod developers to work with.

Chat reporting

Today, Microsoft is developing a chat reporting feature for Minecraft, forcing all chat messages to be cryptographically signed by a key identifying your user account. Upon receiving a report of an inappropriate chat message, Microsoft will see the message and its context, and will be able to link that message uniquely to your Microsoft account. The chat reporting system is integrated with the newly enforced Microsoft authentication system, such that Microsoft can unilaterally ban players from logging in to any multiplayer servers.

Once again, Microsoft is imposing new global policies to restrict how individual server operators and players are allowed to use the game. Despite the game's history of success as a decentralized, community-led effort. Despite Big Tech's continued demonstration that moderation doesn't work at scale.

A solution?

It may not be too late to put control back in the hands of the community. Minecraft has always had an impressive modding ecosystem, often pioneering the state-of-the-art in Java decompilation and code injection.

If we can decouple the Minecraft server and client implementations from Microsoft's authentication servers altogether, we can save the community from future attacks. A decentralized authentication system also opens the door to cleanroom third-party server and client implementations that can be fully interoperable with official implementations, and yet no longer subject to Microsoft's EULA enforcements.

Let's do it!

Disclaimer

On piracy

Decentralized Auth is not intended as a piracy tool, and should only be used in an official Minecraft client or server release by players who have legitimately purchased Minecraft.

That being said, if your legitimate Minecraft account was banned as a result of the chat reporting features introduced in 1.19.1, you still own a license to the game, so you'd have a decent case for using this to connect to compatible servers. We'd still recommend talking to your lawyer though.

On being an unofficial tool

The Decentralized Auth developers are in no way affiliated with Mojang or Microsoft, and Decentralized Auth is not an official Minecraft modification.

User guide

Warning: Decentralized Auth is currently in Beta, so there may be breaking protocol changes in the future. Proceed with caution and prepare to have your server and client mod versions updated together!

Decentralized Auth is currently released for Fabric 1.19 on Modrinth.

Fabric client instructions

  1. Install the Fabric Loader, and create a modded Minecraft 1.19 version. This is required for the official Minecraft Launcher, although other launchers may have it installed by default.
  2. Install the Fabric API for Minecraft 1.19 by placing the JAR file in your .minecraft/mods folder.
  3. Install Decentralized Auth for Minecraft 1.19 by placing the JAR file in your .minecraft/mods folder.
  4. Start your modded Minecraft 1.19 install. You should be able to connect to Decentralized Auth servers now, such as the public demo server.

Fabric server instructions

  1. Install the Fabric Server Launcher.
  2. Install the Fabric API for Minecraft 1.19 by placing the JAR file in your server's mods folder.
  3. Install Decentralized Auth for Minecraft 1.19 by placing the JAR file in your server's mods folder.
  4. Start your modded Minecraft 1.19 install. You should be able to connect to Decentralized Auth servers now, such as the public demo server.

Customizing your player

You can add a skin to your Decentralized Auth player by saving a valid skin texture to .minecraft/decentralizedauth/client/SKIN.png in your modded client version's data directory.

You can also add a cape texture by saving it to .minecraft/decentralizedauth/client/CAPE.png. If you're looking for a cape texture to use, you can try the official Decentralized Auth cape!

Other mod loaders and Minecraft versions

Support for other mod loaders and versions is planned but not yet started. If you'd like to see a particular setup prioritized, please add a 👍 to the corresponding issue(s) on GitLab, or create a new issue if one doesn't exist.

Demo server

Decentralized Auth has an official demo server at mc.decentralizedauth.net. This demo server is running Minecraft 1.19 with the latest release of Decentralized Auth on Modrinth.

Whitelist access

There is a whitelist on the server. If you'd like to gain access, please inquire on our chatroom using Discord or Matrix. Include the UUID of the player you'd like to have added to the whitelist, and/or your official account's username if you'd like to connect with your official account. For now, you can find your player's UUID by entering /decentralizedauth player in a singleplayer world with cheats enabled.

Server info

It's a small 4000x4000 world with a focus on testing and community building for anyone interested in Decentralized Auth.

Please read the rules at spawn once you've joined. Your account may be removed from the whitelist if you break any rules.

Dev intro

Decentralized Auth is developed as a community-driven project. Your contributions are appreciated, no matter what size or shape.

Project discussion is currently handled on the Discord server, which is also bridged to Matrix.

Also check the project's GitLab repo and issue tracker.

The current development roadmap is laid out under the High level overview page.

High level overview

Note: The following document proposes a roadmap. Most features here have not yet been implemented, and are still open to feedback from the community!

If you have suggestions or concerns, please raise them in our Discord server, bridged Matrix server, or GitLab repo issue tracker.

Client initialization

When a client launches for the first time, it should create a new secure random Ed25519 identity keypair. Users should have the option of saving the keypair on disk, or entering it as-needed from a password manager. There should be some UI for importing/exporting and managing multiple identities from the Minecraft title screen. This menu can also include management of the user's profile name and skin texture for each identity.

Saved servers should display a status indicator for whether or not they advertise support for Decentralized Auth (see Server initialization for more details).

Server initialization

When a server launches for the first time, it should create a new secure random Ed25519 identity keypair. The keypair should be saved to disk.

Servers should broadcast that they accept Decentralized Auth in their server metadata by adding an additional numeric JSON field: decentralizedAuth: 1. The number presented in the JSON field is intended to be incremented in the case of an incompatible protocol upgrade. Clients should explicitly check that the number is 1 and avoid trying to login to a server which presents a higher number. A state-of-the-art cryptographic signature algorithm was chosen for identity proofs, so protocol upgrades are not expected to be common, but in the far future it may be necessary to switch to a more secure algorithm. There is no expectation of compatibility or built-in migratability between clients and servers using different Decentralized Auth protocols.

Connection process

In order to maintain compatibility with Microsoft account logins, the Decentralized Auth process is implemented using a completely new login handler. Mixing in to the existing login handler was considered, but too many changes are necessary than it's actually worth.

First, the client sends a handshake with a unique "next state" value to the server. Official server implementations read this value from a packet as a VarInt, so we have plenty of values to choose from. It should be safest to select a relatively small value that still fits into a single byte, while still giving some distance from the current largest value (i.e., 2) in the case of future updates to the official protocol. According to the above criteria, a value of 69 should be sufficient. The existing handshakes require a followup packet from the client, even if there's no new information to send, so the client will send an empty Decentralized Auth Start packet.

When the server receives a handshake with a next state of 69, it will expect a corresponding Decentralized Auth start packet. Then it will generate a new ephemeral X25519 keypair for transport encryption and send the public key in an Encryption Request packet.

The client will respond by generating its own ephemeral X25519 keypair and sending the public key in an Encryption Response packet.

At this point, both the client and server complete the X25519 key exchange and agree on a shared secret. They will use the shared secret to derive 16-byte AES CFB8 stream ciphers using HKDF with a Blake2b digest function. The client and server enable encryption on all future packets in the session using these ciphers, as in the vanilla online login protocol.

Next, the server will send an Auth Challenge packet. The packet includes the server's proof of identity in the form of its own Ed25519 identity public key as well as a signature of the shared secret from the encryption steps, signed using the identity private key.

When the client receives the server's identity public key and signature, it should verify that the signature corresponds to the correct public key. If not, it should end the connection immediately with a protocol error. If the client has connected to the same server before, it should also verify that the identity public key is the same as it was in any previous connections. If not, some warning about MitM interference can be shown to the user so they can reconsider if they want to join. If the joining process continues, the client will send an Auth Proof back to the server, which similarly contains its own Ed25519 identity public key and signed shared secret.

The server should similarly verify that the client's signature matches its advertised public key. At this point, the server can derive the client's UUIDv5 using the client Ed25519 identity public key. It should check whether or not to reject the player based on any configured whitelists, banlists, etc. Then, it will send a Profile Request packet. Vanilla servers keep a cache of user's profiles that is updated at each login; if the server has a cached profile for the player it should send it in the profile request. The cached profile includes the player's last known username and SHA256 hashes of their last used skin and cape textures.

The client should respond with a Profile Response packet. This packet sends the client's desired profile, including its preferred username (which may be different from the last known username) and optionally its preferred skin/cape textures if the server's cached versions do not match the desired ones.

At this point the server will run a login hook based on the client's requested profile. The login hook is a modular component that allows the server to enforce additional custom policies for users based on their requested usernames and public key identities. If desired, the login hook may re-assign the player's username or deny the login request.

If the server has received skin data in the profile request, it should validate that they obey vanilla criteria for length and size, respectively. It should cache the latest skin texture for any Decentralized Auth UUID that connects to the server. Caching textures ensures that the server can save bandwidth on future connections, and also allows them to be served to other players who log in later. The server should finally send the Login Success packet with the profile information selected by the login hook, creating the player's in-game representation and beginning the gameplay session.

Auth config

Servers should be able to configure whether or not to accept vanilla connections. By default, vanilla connections are accepted.

Stretch goals

E2E encrypted messaging between Decentralized Auth clients

This feature would be enabled on the server by default. However, the server can refuse to forward E2E encrypted message packets if sideband messaging might interfere with in-game mechanics.

Non-goals

Account migration / mirroring tools

Players may wish to have server progress from their official Minecraft account moved and/or mirrored to a Decentralized Auth account. This is understandable but would be best served as an alternate, general-purpose account migration tool that can transfer all data from any player's UUID to another.

Broader web3 integration, ICO, NFT skins, etc.

This is just an authentication tool, for logging in to a Minecraft server using a unique private key. If you want, nobody's stopping you from building an ENS-like blockchain registry for Minecraft account names and content-addressed skins on top of it! Keeping Decentralized Auth composable allows different servers to support different use-cases.

Avoiding UUID conflicts

Vanilla Minecraft uses Type 4 UUIDs to uniquely identify players. A primary goal of Decentralized Auth is to avoid unnecessarily fragmenting the existing Minecraft ecosystem by optionally allowing servers which can accept vanilla clients alongside Decentralized Auth clients. That means it's important to choose UUIDs that are guaranteed not to collide with ones provided by Mojang/Microsoft, while still sharing the same format.

Type 4 UUIDs are randomly generated apart from either 6 or 7 bits to indicate the type and variant:

b876ec32-e396-476b-a115-8438d83c67d4
              ^
              always `4` in a version 4 UUID

Type 5 UUIDs, on the other hand, are generated based on a SHA-1 hash of the content they identify. Content-addressing is a great fit for decentralized systems like IPFS, so Type 5 UUIDs are a great fit for Decentralized Auth.

The type field in Type 5 UUIDs is always a 5, so there's a guarantee of no collisions!

04e0eded-79f2-5f74-bbac-91aeb50cf540
              ^
              always `5` in a version 5 UUID

The namespace selected for Decentralized Auth player UUIDs is 588672c8-7f77-43fc-98e7-0413caee61d4.

SHA-1 itself is no longer cryptographically secure against collisions on specially-crafted input pairs. This should be mitigated by having each player generate their own secure keypair using a modern asymmetric encryption algorithm, such that the public key is sufficiently unpredictable and relatively expensive to brute force. A player's Decentralized Auth UUID should only ever be derived from a public key after verifying that they have access to its corresponding private key.

Username policies

On vanilla servers, players have unique UUIDs and usernames. They're free to change their username by requesting a new one from Microsoft, but Microsoft ensures that there are never any duplicate usernames (although there have been rare duplicate name exploits in the past).

The core mechanism of Decentralized Auth is cryptographic protection against duplicate UUIDs, but not protection against duplicate usernames. While Minecraft still works with duplicated usernames, it can be extremely confusing for onlookers, and many admin commands will select a single arbitrary player with the provided username without providing any mechanism for choosing by UUID instead. Most server admins will be interested in using a policy to enforce unique usernames.

Decentralized Auth is a player authentication system and not a username assignment system, but the problem of duplicate usernames is important, common, and specific to alternative authentication systems, so Decentralized Auth provides some basic tools for dealing with it. However, usernames are complicated and there are many possible ways that a server admin may wish to manage usernames. Ultimately, the intention is for Decentralized Auth to expose a generic username policy API such that plugin developers can create, share, and deploy their own custom logic for username management.

This document provides some technical details about username management using Decentralized Auth, as well as some examples of policies that server admins may wish to implement or adopt.

Bare minimum policy

The first release of Decentralized Auth will provide a very minimal set of serverside config for username management, taking advantage of the vanilla UserCache. Improvements to this policy should not affect the network protocol at all, so it should be possible to perform backward-compatible upgrades in the future.

  1. Allow username changes: true/false (default false)
    • If true, the server will request the player's username each time they join.
    • If false, the server will always attempt to pull the player's username from the UserCache whenever they join the server, only requesting a new username if one cannot be found.
  2. Prevent duplicate usernames: true/false (default true)
    • If true, the server will always check the UserCache for players with the requested username when a player joins a server. If another player has already logged in with the requested username previously, the new player will be denied login.
    • If false, the server will always allow users to login with their requested username. This is generally not recommended.
  3. Precedence to official Minecraft account usernames: "strict"/"prefer"/"none" (default "prefer")
    • "strict": It is impossible for a Decentralized Auth player to join a server with a username currently used by any official Minecraft account.
    • "prefer": Decentralized Auth players may choose a username of an official Minecraft account, but they will lose the rights to that name if and when the official account joins the server for the first time.
    • "none": Official Minecraft account usernames get no special treatment. Official Minecraft accounts may be unable to join the server while a Decentralized Auth player has the same name.

Note that the vanilla UserCache expires cached profiles after 1 month, after which point a username can be reclaimed or changed without restrictions.

Policy examples

The following assortment of username management policy options is intended to demonstrate the complexity of username management, and serve as a reference when designing a more flexible policy API. Note that several of these options could be in use simultaneously. If you have a use-case that isn't described here, please open an issue or PR to add it.

Reserve on first use

The server requests a player's username when they join the server for the first time, at which point that username will be immediately reserved to that player's UUID.

Revoke when using a new name

If a player with an existing username reservation ever joins the server with a different username, the previous username reservation will be removed so that the original username can be used by another player.

Reservation expiration

Username reservations optionally expire after a configurable amount of offline time to mitigate name-squatting (since Decentralized Auth identities are essentially "free" to create).

Official Minecraft account usernames

Precedence can optionally be given to official Minecraft account usernames in a few different ways, as described above.

By playtime

Whenever a player joins a server with a particular username, they begin to accumulate "stake" in the username proportional to the amount of time they are online with that username. The username is reserved for the player above a minimum threshold of stake. Stake may also optionally decay or grow over offline time at a certain rate.

External registration

Server admins may operate a website where players must sign up for an account in order to be whitelisted on the server. They can tie the usernames on the Minecraft server to username registrations on the website. This might involve any kind of logic, possibly including payment for a username reservation as a premium feature.

Fully decentralized username service

A server admin may choose to only respect username reservations posted on a decentralized ledger, such as a blockchain.

Skin textures

Vanilla Minecraft servers fetch player skin texture information from Mojang servers in the form of signed base64-encoded JSON blobs. Importantly, there is no texture data included in these blobs, just URLs. Clients must fetch the actual texture data from those URLs, and the vanilla client code enforces that the URLs are subdomains of either minecraft.net or mojang.com.

The entire texture information blob is also signed by Mojang-owned private keys. Clients will reject any skin texture information that does not have a valid signature from Mojang.

The domain and signature restrictions in the vanilla client mean that the usual skin APIs are incompatible with decentralization. Skin customization is an important part of identity as well, as it's a major way for players to express themselves. By that logic, skins are well within the scope of features that Decentralized Auth should provide an alternative solution for.

Implementation details

For the sake of decentralization, it must be possible for a server to determine its own policy for skins and apply that to players who join. Players must also be able to make a direct request that the server assigns them a particular skin. The server may still choose not to honor such requests if, for example, it's a themed server that gives players a specific skin or transforms the requested skin in a certain way.

Player skin requests

As part of the login process, the server requests profile information from the player. Inside the profile request, the server includes the cached profile information for the player's last login session, if it exists. The cached profile information includes the player's previous skin hashes. This way, players don't need to send any skin textures if they haven't changed them since their last online session, saving server bandwidth.

Clients respond to the profile request by sending requested profile information, followed by any texture data that was not present in the server's cached profile information packet. Once a Decentralized Auth player logs in with a particular skin, the server should cache the skin for players who log in later, and for future logins of the same player.

Skin texture property packets

For a server to be able to apply its own skin policy to players, it must be able to send a skin texture directly to clients. The vanilla GameProfile class stores players' UUIDs and usernames, in addition to a completely freeform/extensible set of properties. Vanilla skin textures are described in the properties set, so the logical choice is for Decentralized Auth servers to use the same extensible set of properties to describe textures as well.

As per wiki.vg, the vanilla textures property is formatted as follows, encoded in base64:

{
    "timestamp": <java time in ms>,
    "profileId": "<profile uuid>",
    "profileName": "<player name>",
    "signatureRequired": true,
    "textures": {
        "SKIN": {
            "url": "<player skin URL>"
        },
        "CAPE": {
            "url": "<player cape URL>"
        }
    }
}

"timestamp", "profileId", "profileName", and "signatureRequired" are all not useful to clients since they are simply providing extra context for the integrity of the signature. Decentralized Auth clients should be modded to accept unsigned skin texture packets from the server.

The only useful data is the actual texture provided in "SKIN", "CAPE", and "ELYTRA" (although Elytra textures are embedded in the cape texture image, so "ELYTRA" seems to be unused in practice). The vanilla client supports arbitrary additional metadata in a "metadata" map alongside "url" in each of these structures. "SKIN"'s metadata may include a "model" field, with a value of either "default" or "slim".

Despite the presence of useless information in the packet, for optimal backwards and forwards compatibility, the same data structure should be preserved such that future versions can keep up with additional properties as they are added in the vanilla client. It's also best to maintain the same semantics, where the full texture data is not included directly in the packet, to prevent hogging the server bandwidth in cases where these packets are sent multiple times.

Once again, content-addressing is a good fit. Each texture can use "metadata" to store a new "textureSha256" field, holding the SHA256 hash of the image data. An additional gameplay packet will be added to support pulling a texture with a particular SHA256 hash directly from the server. Clients should cache the textures they receive to minimize bandwidth load on the server.

Custom skins in vanilla clients

Vanilla players by default would not be able to fetch skins for any Decentralized Auth players, whose UUIDs cannot have corresponding skins uploaded to official Mojang servers. It is possible to assign a player's skin using an arbitrary packet from the server-side (even if the "profileId" is for a different player), but the data still has to have been signed by Mojang. This can be accomplished with an account pool as per this Spigot forum thread. MineSkin provides an account pool like this as a public service, or server admins could optionally configure a different endpoint to use. If no signed skin data can be retrieved, there can be a fallback to a configurable default account's skin, or just default Minecraft skins.

Delivering custom skins

The vanilla server already has a packet that pushes profile information, including the skin properties above, to clients.

Decentralized Auth servers should continue to use these packets as they normally would, although the skin properties may be modified depending on the player they're being sent to and the player receiving the packet.

  • All players receive skins of vanilla players the same way as in the vanilla client (Mojang-signed packets including Mojang URL endpoints)
  • Decentralized Auth players receive skins of Decentralized Auth players directly from the server (unsigned packets with a textureSha256 that can be requested from the server)
  • Vanilla players receive skins of Decentralized Auth players from a configurable skin pool (Mojang-signed packets forwarded from the official MineSkin API by default)

Miscellaneous design choices

Why SHA256?

Although there are more modern hash algorithms available, SHA256 should be sufficient for a very long time. Mojang happens to use SHA256 content-addressing for their own skin texture endpoints; i.e. the query http://textures.minecraft.net/texture/<SHA256> will return the skin with the provided hash, and the client creates SHA256 hash-based identifiers for the in-game textures. Although there's still a lot of patching required to support decentralized skins, using the same hash algorithm keeps things slightly more unified and allows already-downloaded cached textures to work without needing to be fetched again.

SHA256 is also the default hash algorithm used by IPFS. While Decentralized Auth doesn't use IPFS by default, it'd be really neat to eventually have skin repositories that store skin textures on IPFS, and maybe even built-in IPFS nodes in the server and/or client.

Player-signed skin packets?

Theoretically, clients could generate a textures packet like the ones from Mojang, and sign them using their Decentralized Auth identity keys. This could be a neat way to ensure that the server has no way to tamper with player-generated skins, although in practice, it is very difficult for players to guarantee that the server is not MITM'ing connected users at scale. It would only be effective for users who are able to verify each others' identities through a sidechannel that is not controlled by the server admins. Thus it's probably not worth the additional complexity.

Protocol

This page provides technical details about the packet formats introduced by Decentralized Auth. The format is heavily inspired by wiki.vg's Protocol document.

Handshaking

See wiki.vg's Handshaking protocol document. Decentralized Auth reuses the same packet but sets Next State to a value of 69 to indicate a transfer to the Decentralized Auth flow.

Decentralized Auth

The Decentralized Auth login process is as follows:

  1. C→S: Handshake with Next State set to 69 (Decentralized Auth)
  2. C→S: Decentralized Auth Start
  3. S→C: Encryption Request
  4. C→S: Encryption Response
  5. Client and server enable encryption
  6. S→C: Auth Challenge
  7. C→S: Auth Proof
  8. Server enforces banlist/whitelist by IP and UUID
  9. S→C: Profile Request
  10. C→S: Profile Response
  11. Server runs login hook based on the requested profile
  12. S→C: Set Compression (optional)
  13. S→C: Decentralized Auth Success

Clientbound

Disconnect

Packet ID
State
Bound To
Field Name
Field Type
Notes
0x00
Decentralized Auth
Client
Reason
Chat
The reason why the player was disconnected

Encryption Request

Packet ID
State
Bound To
Field Name
Field Type
Notes
Public Key Length
VarInt
Length of Public Key
0x01
Decentralized Auth
Client
Public Key
Byte Array
Server's ephemeral X25519 public key, in bytes

Auth Challenge

Packet ID
State
Bound To
Field Name
Field Type
Notes
Identity Public Key Length
VarInt
Length of Identity Public Key
Identity Public Key
Byte Array
Server's Ed25519 Identity Public key, in bytes
Length of signed shared secret
VarInt
Length of the signed shared secret
0x02
Decentralized Auth
Client
Signed shared secret
Byte Array
Shared secret signed by the identity Ed25519 key

Profile Request

Packet ID
State
Bound To
Field Name
Field Type
Notes
Has Profile Data
Boolean
Whether or not the remaining fields are present
UUID
UUID
Username
String (16)
Number of Properties
VarInt
Number of elements in the following array
Name
String(32767)
Value
String(32767)
Is Signed
Boolean
Generally false for Decentralized Auth
0x03
Decentralized Auth
Client
Property
Signature
Array
Optional String(32767)
Only if Is Signed is true

Compression Request

This is the same as the vanilla Compression Request packet. The Packet ID is 0x04.

Login Success

Packet ID
State
Bound To
Field Name
Field Type
Notes
UUID
UUID
Username
String (16)
Number of Properties
VarInt
Number of elements in the following array
Name
String(32767)
Value
String(32767)
Is Signed
Boolean
Generally false for Decentralized Auth
0x05
Decentralized Auth
Client
Property
Signature
Array
Optional String(32767)
Only if Is Signed is true

Serverbound

Decentralized Auth start

Packet ID
State
Bound To
Field Name
Field Type
Notes
0x00
Decentralized Auth
Server
(empty packet)

Encryption Response

Packet ID
State
Bound To
Field Name
Field Type
Notes
Public Key Length
VarInt
Length of Public Key
0x01
Decentralized Auth
Server
Public Key
Byte Array
Client's ephemeral X25519 public key, in bytes

Auth Proof

Packet ID
State
Bound To
Field Name
Field Type
Notes
Identity Public Key Length
VarInt
Length of Identity Public Key
Identity Public Key
Byte Array
Server's Ed25519 Identity Public key, in bytes
Length of signed shared secret
VarInt
Length of the signed shared secret
0x02
Decentralized Auth
Server
Signed shared secret
Byte Array
Shared secret signed by the identity Ed25519 key

Profile Response

Packet ID
State
Bound To
Field Name
Field Type
Notes
UUID
UUID
Username
String (16)
Number of Properties
VarInt
Number of elements in the following array
Name
String(32767)
Value
String(32767)
Is Signed
Boolean
Generally false for Decentralized Auth
Property
Signature
Array
Optional String(32767)
Only if Is Signed is true
Number of Textures
VarInt
Number of elements in the following array
Type
String(32767)
Only "SKIN" and "CAPE" are valid
0x03
Decentralized Auth
Server
Property
Value
Array
Byte Array(16384)
PNG data matching any texture SHA256 hashes requested

Play

Note that the Play packets for Decentralized Auth are implemented as plugin messages.

Clientbound

Texture Response

Plugin Channel
State
Bound To
Field Name
Field Type
Notes
SHA256 Length
VarInt
Length of SHA256 hash
decentralizedauth:textures
Play
Client
SHA256
Byte Array
SHA256 hash in bytes

Serverbound

Texture Request

Plugin Channel
State
Bound To
Field Name
Field Type
Notes
Texture Data Length
VarInt
Length of Texture Data
decentralizedauth:textures
Play
Server
Texture Data
Byte Array
Texture Data in bytes