Why are the UUIDs changing in offline mode?

In my plugin I’m trying to check if a player bought Minecraft or is using a cracked account. The obvious way to do this is to use the Web API provided by Mojang to compare the UUID I have with the one Mojang has…
Problem is, when the server is in offline mode the UUIDs don’t match, while in online mode they do.

So my question is: Why is Sponge assigning their own UUIDs and (how) can I get around that?

(Sponge Forge 3.1.0)

Thanks in advance!

UUIDs in offline mode are somehow generated from the username. UUIDs in online mode are fixed and don’t have anything to do with the username. So the user TestUser has a different UUID in online and offline mode, that’s intended behavior. There is no reliable method to identify players in offline mode, therefore it is also called insecure mode and the Minecraft server warns the admin when it is start up in offline mode.

It has nothing to do with sponge

Minecraft uses name based UUIDs in Offline Mode.
UUID.nameUUIDFromBytes(("OfflinePlayer:" + player).getBytes(UTF_8))
Online Mode UUIDs are random ones generated when the account is created:
UUID.randomUUID()

To answer your question:
Sponge is doing nothing different from vanilla here.
And you cannot get around that UUIDs in offline mode are different.
Use online mode.

Why are you doing this?

Using online mode will prevent cracked users from joining just fine.

If you need to use offline mode for bungee, then enabling the ip forwarding settings, as well as setting up your firewall correctly should both fix the UUID’s (If you have bungee set up correctly the UUID is forwarded as well, as far as I know) and prevent cracked players from joining directly.

Thank you!

Sorry I didn’t know it’s the nativ behavior of Minecraft.

Hello. I was trying to find something that could tell me how an offline UUID is being generated and found this thread. However, given the fact that the UUID is an MD5 hash, I tried to generate one and it produces different hash. It looks similar, but it’s different in few bits:

d5fc4f55-35fc-3de6-8e3c-03c25cd1ed19 ← generated using Offline Player UUID generator (and it matches with the offline UUID used on offline servers)
d5fc4f55-35fc-cde6-4e3c-03c25cd1ed19 ← generated using provided string format in an independent MD5 hash generator (used two different ones independent on each other, same result)

You can see that two hexadecimal digits are different. I’ll try to generate it using a Java code with the UUID, but are you sure that this is exactly how it is generated in the game? I never found the original source code that is responsible for that, so I don’t know. Do you have a link to the original source code so I can look myself? Google isn’t much helpful in this case.

EDIT: So yes, it does indeed work as intended with the Java UUID object. Well, thank you I guess :smiley:

FWIW, to explain:

The source of Minecraft is not public so I cannot give a link to it, but you can set up a mod developer environment and browse the decompiled code that way.

The source of Java’s UUID.nameUUIDFromBytes can be found here:

https://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/util/UUID.java#l162

Specifically:

        md5Bytes[6]  &= 0x0f;  /* clear version        */
        md5Bytes[6]  |= 0x30;  /* set to version 3     */
        md5Bytes[8]  &= 0x3f;  /* clear variant        */
        md5Bytes[8]  |= 0x80;  /* set to IETF variant  */

If we look at the UUIDs in question:

d5fc4f55-35fc-3de6-8e3c-03c25cd1ed19
d5fc4f55-35fc-cde6-4e3c-03c25cd1ed19

We can see that byte 7 (md5Bytes[6]) and byte 9 (md5Bytes[8]) are different, which corresponds to the transformation that UUID.nameUUIDFromBytes performs.

These transformations are required for it to be a valid version 3 UUID. More info can be found on Wikipedia:

and on the RFC: rfc4122