Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Classic 0.0.17a up to 1.6.4 support #52

Open
catfromplan9 opened this issue Mar 11, 2024 · 13 comments
Open

Classic 0.0.17a up to 1.6.4 support #52

catfromplan9 opened this issue Mar 11, 2024 · 13 comments
Labels
documentation Improvements or additions to documentation enhancement New feature or request medium priority

Comments

@catfromplan9
Copy link
Contributor

I have only checked for beta 1.7.3, since most beta players prefer this version, but to implement support for it should be feasible. Authlib did not exist at the time, instead URLs are hardcoded to be used, but they're all http so using jvm proxy argument you can reroute these API endpoints to any drasl instance.

For skins, http://s3.amazonaws.com/MinecraftSkins/PlayerName.png is checked, and the skin returned should be a 64x32 image (old skin format) with any layers merged into 1 layer.

For authentication, http://www.minecraft.net/game/joinserver.jsp is checked by the client and http://www.minecraft.net/game/checkserver.jsp is checked by the server. I do not know how these APIs work.

The skins endpoint is offline, but the joinserver.jsp and checkserver.jsp endpoints are online however they've been moved to https://session.minecraft.net (https://session.minecraft.net/game/joinserver.jsp and https://session.minecraft.net/game/checkserver.jsp respectively)

Here is the source code from beta 1.7.3 referencing these URLs that I hope can help with implementing this.

Authentication:
https://github.com/jacobo-mc/mc_b1.7.3_release/blob/main/1.7.3-LTS/src/minecraft/net/minecraft/src/NetClientHandler.java - Client
https://github.com/jacobo-mc/mc_b1.7.3_release/blob/main/1.7.3-LTS/src/minecraft_server/net/minecraft/src/ThreadLoginVerifier.java - Server

Skins:
https://github.com/jacobo-mc/mc_b1.7.3_release/blob/main/1.7.3-LTS/src/minecraft/net/minecraft/src/EntityPlayerSP.java - Self
https://github.com/jacobo-mc/mc_b1.7.3_release/blob/main/1.7.3-LTS/src/minecraft/net/minecraft/src/EntityOtherPlayerMP.java - Other players

@catfromplan9
Copy link
Contributor Author

@catfromplan9
Copy link
Contributor Author

You can see a craftbukkit fork's authentication API implementation here https://github.com/RhysB/Project-Poseidon/blob/master/src/main/java/com/legacyminecraft/poseidon/util/SessionAPI.java

@catfromplan9
Copy link
Contributor Author

For checkserver.jsp, it works as follows

http://(www|session).minecraft.net/game/checkserver.jsp?user=USERNAME&serverId=IDENTIFIER

USERNAME is the player's username, for example Steve

IDENTIFIER is a bit more complex. It is a random hexadecimal value given to the client by the server, which the client will set by calling the joinserver.jsp endpoint

The content-type is application/json for these endpoints

For a request to checkserver.jsp, it will always respond with HTTP 405 and content of "NO" if any parameters are missing or if that user account has not made a request to the joinserver.jsp endpoint with the given parameter. If the user account has sent to the joinserver.jsp endpoint that parameter, then it replies with a HTTP 200 and content of "YES"

This should be all you need to get checkserver.jsp implemented

@catfromplan9
Copy link
Contributor Author

catfromplan9 commented Mar 19, 2024

Alright, for joinserver.jsp, heres how it works

http://(www|session).minecraft.net/game/joinserver.jsp?user=USERNAME&sessionId=SESSION&serverId=IDENTIFIER

USERNAME and IDENTIFIER works as before, except that here IDENTIFIER is being set so that when the endpoint is queried by the server with checkserver.jsp it will return "YES" instead of "NO". SESSION is, I believe, the session token.

Just like before, content-type is application/json on all responses

I am not sure what is returned when it is successful, but if the username and session token do not correspond to the same account or if the session token is invalid/not specified, the server will always respond HTTP 405 with content "Bad login"

@catfromplan9
Copy link
Contributor Author

catfromplan9 commented Mar 29, 2024

To fix skins on classic up until beta 1.2_02, add alternative endpoint of skins for http://www.minecraft.net/skin/playername.png and http://www.minecraft.net/skins/playername.png

@catfromplan9
Copy link
Contributor Author

catfromplan9 commented Mar 29, 2024

As for Cloaks, http://www.minecraft.net/cloak/get.jsp?user=username is used in beta 1.0, and in beta 1.3 until release 1.2, http://s3.amazonaws.com/MinecraftCloaks/username.png is used

Add alternate endpoints for http://www.minecraft.net/game/joinserver.jsp and http://www.minecraft.net/game/checkserver.jsp at http://session.minecraft.net/game/joinserver.jsp and http://session.minecraft.net/game/checkserver.jsp since modded clients and servers tend to use these

^ beta 1.8 up until release 1.6.1 uses these endpoints too

In release 1.3, skins and cloaks endpoint was moved to
http://skins.minecraft.net/MinecraftCloaks/username.png and http://skins.minecraft.net/MinecraftSkins/username.png respectively. Again, more alternate endpoints are necessary

In release 1.5, snooper was added URL("http://snoop.minecraft.net/" + paramString + "?version=" + '\001');. This isnt relevant unless you decide to add telemetry to drasl, which I don't see a point with.

Finally, in release 1.6 the authentication is changed to modern logic and in 1.7 old code was removed. So, with all these API endpoints for checkserver, joinserver, and skins+cloaks, it will support classic (when skins were introduced, pre-authentication even) up until release 1.6.1.

In release 1.8, the modern logic is used for skins/capes too and authlib-injector functions as you would expect. I should note though, that the MinecraftSkins endpoint is still present (not MinecraftCloaks though) so I would have to check if it does anything in game.

@catfromplan9 catfromplan9 changed the title Minecraft beta (and alpha?) support Minecraft Classic up to 1.6.1 support Mar 29, 2024
@catfromplan9
Copy link
Contributor Author

And for capes, the legacy cape format will need to be use where the cape is cropped to the corner

@catfromplan9
Copy link
Contributor Author

catfromplan9 commented Mar 29, 2024

Authentication did not exist from classic up until alpha 1.0.15 (alpha server 0.1.0). Authentication was added in alpha 1.0.16 (alpha server 0.1.1) and uses the same format specified here. In these earlier versions, drasl can be used for skins and nothing more I was wrong, the session token is still being sourced even in classic. After classic, multiplayer was not readded until alpha and when it was it was completely recoded to the implementation I discuss here. https://wiki.vg/Classic_Protocol#Heartbeats

@catfromplan9 catfromplan9 changed the title Minecraft Classic up to 1.6.1 support Alpha 1.0.16 (Classic for skins) up to 1.6.1 support Mar 29, 2024
@catfromplan9
Copy link
Contributor Author

I've forgot about login api, it is explained here

https://wiki.vg/Legacy_Minecraft_Authentication

This appeared some time before beta 1.7 and after beta 1.4, unfortunately it is in HTTPS. However, it should be noted that this appears unnecessary.

From a version of classic: com/mojang/minecraft/MinecraftApplet.java: this.minecraft.h = new a(this.getParameter("username"), this.getParameter("sessionid")); <- this exists in all versions up until release 1.5. Release 1.6 switched to yggdrasil but supports the old authentication scheme too (checkserver & joinserver endpoints present)

It appears to me that the launcher sets this, so this API endpoint does not need to be implemented

@catfromplan9 catfromplan9 changed the title Alpha 1.0.16 (Classic for skins) up to 1.6.1 support Classic up to 1.6.1 support Mar 29, 2024
@catfromplan9
Copy link
Contributor Author

catfromplan9 commented Mar 29, 2024

The authentication for alpha->1.6.1 is documented here at the bottom of the page: https://wiki.vg/index.php?title=Session&oldid=3107#Joining_a_Server
Here is a newer revision https://wiki.vg/index.php?title=Session&direction=next&oldid=3112

Keep in mind, session.minecraft.net and www.minecraft.net need to both be implemented. session.minecraft.net is used in b1.8+ and www.minecraft.net is used prior to that

@catfromplan9 catfromplan9 changed the title Classic up to 1.6.1 support Classic up to 1.5.2 support Mar 30, 2024
@catfromplan9 catfromplan9 changed the title Classic up to 1.5.2 support Classic 0.0.17a up to 1.5.2 support Mar 31, 2024
@catfromplan9 catfromplan9 changed the title Classic 0.0.17a up to 1.5.2 support Classic 0.0.17a up to 1.6.4 support Apr 2, 2024
@catfromplan9
Copy link
Contributor Author

Update regarding versions:

Release 1.5.2 and below use fully the legacy authentication system, and so the proxyHost implementation works for them

Release 1.6.1-1.6.4 seem to use authlib for accessing the same legacy skins API and doing legacy authentication. With authlib-injector, skins are successfully obtained via yggdrasil (not capes though). Adding -Dhttp.proxyHost to send requests to my own skin server has no effect, but editing the hosts file works. I assume authentication is the same. It seems that the game itself no longer handles skins/capes (maybe an old version of authlib does it instead, with non-yggdrasil support?)

Release 1.7.2 and above use authlib for everything, but capes do not function. Skins work fine though. This is possibly related to some kind of change in how the API functions, so authlib-injector and drasl may need updates to support capes on 1.6.1-1.7.5. See the 1.7.6 changelog:

Skins and capes are now distributed through servers.

https://minecraft.wiki/wiki/Java_Edition_1.7.6

So, for 1.6.x support of authentication and capes (and just capes support on 1.7.2), authlib-injector would need to support the pre-1.7.6 capes API implementation and pass any http://session.minecraft.net requests authlib makes(? or some library that isn't the game itself but I assume authlib) through the proxy. Usecase unclear for playing Minecraft 1.6 though, so I consider this really low priority.

@catfromplan9
Copy link
Contributor Author

-Dhttp.nonProxyHosts can be used to specify domains to not proxy, each seperated by a pipe character ('|')

@Midou36O
Copy link

@evan-goode We're currently trying to figure out a solution on how to solve this but we need your input on some problems i'm encountering when providing the token from a legacy client, could by any chance check on thr drasl matrix room? (And if appropriate, continue the discussion on important research / implementation points here)

@evan-goode evan-goode added documentation Improvements or additions to documentation enhancement New feature or request medium priority labels Oct 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation enhancement New feature or request medium priority
Projects
None yet
Development

No branches or pull requests

3 participants