Skip to content

Skip the login flow for players authenticated by Minekube Connect - #404

Open
robinbraemer wants to merge 1 commit into
kyngs:devfrom
robinbraemer:connect-support
Open

Skip the login flow for players authenticated by Minekube Connect#404
robinbraemer wants to merge 1 commit into
kyngs:devfrom
robinbraemer:connect-support

Conversation

@robinbraemer

Copy link
Copy Markdown

Hi! This extends the Floodgate exemption to cover Minekube Connect, which conflicts with LibreLogin in the same way and at the same points.

The problem

Connect terminates the player's connection at its own edge, performs the Mojang online-mode handshake there, and then relays the player into the proxy over a local Netty channel. On that inner connection it forces offline mode and supplies the player's real Mojang UUID and skin properties itself.

That means there is no second Mojang session left for the proxy to verify. Three things then go wrong:

  1. Pre-login. VelocityListeners#onPreLogin runs at PostOrder.LAST and BungeeCordListener#onPreLogin at HIGHEST, so LibreLogin's decision replaces Connect's. For any player LibreLogin considers premium the result is FORCE_ONLINE, and the proxy sends an encryption request that can never be answered — the login hangs and never completes. (This is why disabling premium autologin is the workaround people currently use: with no premiumUUID the pre-login result can only ever be FORCE_OFFLINE, which happens to agree with Connect.)
  2. Game profile. onProfileRequest rebuilds the profile from getOriginalProfile(), which discards the UUID and the skin properties Connect put there. This one happens even with autologin disabled, so those players silently get a different UUID and a default skin.
  3. Post-login. onPostLogin and chooseServer then track the player and route them to limbo, because nothing tells them the player is already authenticated.

The fix

Connect marks the connection with a connect-player Netty channel attribute, deliberately mirroring Floodgate's floodgate-player, and it is set when the channel is created — so it is readable everywhere the Floodgate attribute already is, including from handlers registered at the very earliest priority.

So this PR follows the exemption you already have for Floodgate, at the same three points:

  • VelocityListeners#onPreLogin — skip the login flow, right after the existing Floodgate branch. I pulled the channel reflection out of that branch into a getChannel(InboundConnection) helper so both checks share it; the Floodgate branch itself is otherwise unchanged.
  • VelocityListeners#onProfileRequest / BungeeCordListener#onProfileRequest — leave the profile alone, alongside the existing fromFloodgate check.
  • BungeeCordListener#onPreLogin — same guard as the Floodgate one directly above it.
  • AuthenticListeners#onPostLogin and #chooseServer — the existing fromFloodgate checks become externallyAuthenticated, which is fromFloodgate || fromConnect. The Connect path is the same as the Floodgate one: no tracking, straight to a lobby server.

New common/integration/ConnectIntegration, next to FloodgateIntegration, holds the attribute key and the check.

Notes for review

  • No new dependency, and nothing to soft-depend on. Netty interns attribute keys by name, so the attribute is simply absent when Connect is not installed and the check compiles and runs either way. That is also why there is no connectEnabled() gate to match floodgateEnabled() — there are no classes to load, so there is nothing to guard.
  • Post-login lookups need a UUID, but the channel is only reachable during login. So ConnectIntegration remembers the UUIDs it recognises at profile-request time and drops them again in onPlayerDisconnect — the same add-on-login / remove-on-disconnect lifecycle FloodgateApi uses for its own player map. One caveat I want to flag rather than hide: if a connection dies between the profile request and the player object existing, no disconnect fires and that UUID stays in the set. It is bounded (one entry per distinct player, re-adding is idempotent) and only read during join, but if you would rather have an expiring cache there, that is a one-line change and I am happy to make it.
  • The Connect check fails open. If the channel cannot be read it behaves exactly as it did before this check existed, and logs at debug. I deliberately did not extend the Floodgate branch's deny-on-error behaviour to it, so that installations without Connect cannot start failing logins because of this PR.
  • Paper is untouched. The packetevents login path there is a different shape and I had no way to exercise it, so I left it alone rather than guess. The shared AuthenticListeners changes do apply on Paper, but fromConnect is never true there because nothing registers a UUID, so Paper behaviour is unchanged.
  • No test. The project has no test source set, and adding a test framework inside a bug-fix PR seemed like the wrong call. If you would like one, tell me which framework you want and I will add it.

Verified with ./gradlew build (compiles clean, checkLicenses passes). I have not been able to run this against a live Connect + LibreLogin proxy, so a second pair of eyes on the Bungee PendingConnection channel lookup in particular would be welcome.

Reference for the attribute, in case it is useful: https://github.com/minekube/connect-java/blob/main/docs/login-plugin-integration.md.

Connect authenticates the player at its own edge and then relays the
connection into the proxy, so there is no Mojang session left for the
proxy to verify. Forcing online mode on such a connection makes the
proxy send an encryption request that can never be answered and the
login never completes. Rewriting the game profile afterwards also
replaces the real uuid and skin properties Connect supplied.

Connect marks those connections with a "connect-player" channel
attribute, mirroring Floodgate's "floodgate-player" convention, so this
extends the exemptions that already exist for Floodgate to cover them
as well. Reading the attribute needs no compile time dependency,
Netty interns attribute keys by name.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant