Let plugins control the client-facing onlineMode flag (26.2+) when they rewrite the profile UUID
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 2.3k
- Forks
- 960
- Avg merge
- 5d 10h
- Merged PRs (30d)
- 2
Description
Since 26.2 the game join packet carries an onlineMode boolean, and Velocity overwrites whatever the backend sent with player.isOnlineMode() (TransitionSessionHandler, d7ad0522). That mirrors what the client used to derive from Connection#isEncrypted, so it's a sensible default — but the client-facing "online mode" signal is now the proxy's decision, and plugins have no say in it.
Where this bites: premium auto-login plugins force online-mode in PreLoginEvent to verify the Mojang session, then rewrite the UUID back to the offline v3 one in GameProfileRequestEvent so existing world data keeps working. The client is now told it's on an online-mode server while its UUID doesn't belong to the session it authenticated with, so everything that goes through the Mojang session (profile key pair, tab heads, social block lists, mods reading connection.onlineMode()) resolves "me" to a UUID that matches nothing in the world. Report with pets, Chat Heads and Simple Voice Chat breaking while server-side data stays consistent: AuthMe/AuthMeReloaded#3126; the same account logged in as plain offline works fine.
Before 26.2 the mismatch was keyed on encryption itself and nothing proxy-side could change it; now the client trusts the flag, so this is fixable — there's just no way to set it. The only workaround is to skip forceOnlineMode() and redo the encryption / hasJoined handshake via PacketEvents so the login continues as offline: Java AES/CFB8 instead of native ciphers, custom handlers in Velocity's pipeline, and a second copy of login-state handling to maintain.
Two possible shapes, from small to proper:
-
Make the client-facing flag controllable, without changing anything by default:
-
(a) Plugin API — e.g.
GameProfileRequestEvent#setClientOnlineMode(boolean), distinct fromisOnlineMode(), which keeps meaning "authenticated with Mojang". This is what a plugin like AuthMe would call. -
(b) Opt-in config flag that sends
falsewhenever the final profile id differs from the authenticated one. Velocity already treats that mismatch as broken ("UUID for Player mismatches! Chat/Commands signatures will not work correctly" inAuthSessionHandler), and it also happens withplayer-info-forwarding-mode = none— the case #1806 works around on the chat-session side. This covers setups without a plugin in the loop.
-
-
A PreLogin result that verifies the Mojang session but keeps the offline identity — say
verifyOnlineMode(). Same encryption request andhasJoinedasforceOnlineMode(), but afterwards the connection continues down the normal offline path: offline v3 profile from the username,isOnlineMode()false, offline UUID forwarded,falsein the join packet. The verified Mojang profile is handed to plugins separately, e.g.GameProfileRequestEvent#getVerifiedProfile(), to check against a database, forward in a signed message, or copy skin properties from.For AuthMe this replaces
forceOnlineMode()+setGameProfile(profile.withId(offlineUuid))with one result and one getter, and nothing is left to keep consistent by hand: the UUID rewrite goes away because Velocity built the offline profile itself, there's no flag to override becauseisOnlineMode()is genuinely false, and the verified profile comes from the API instead ofgetOriginalProfile(). It's what such plugins emulate today with PacketEvents, done natively.
Option 1a alone would already fix the reported breakage without any plugin touching the pipeline. Happy to help with a PR for either.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with TransitionSessionHandler and AuthSessionHandler to trace how the client-facing onlineMode flag and profile UUID are selected. Then review PreLoginEvent, GameProfileRequestEvent, and forceOnlineMode() to compare the proposed API and verified-profile approaches. Done means an agreed design lets plugins preserve the authenticated profile separately from the client-facing identity without breaking existing defaults.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- authentication, backend, backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100