• v0.2.0 50013a3ae5

    NetworkChorus released this 2026-07-26 16:42:08 +00:00 | 1 commits to main since this release

    Extends SelectiveAuth down to Minecraft 1.3.2, and adds support for
    Legacy Fabric — validated against
    Better Than Wolves: Community Edition.

    The range is now 1.3.2 → 1.21.5

    The structural fingerprint already reached far below the previously tested
    floor. Scanning 1.2.5 through 1.6.4 found the auth gate unchanged on 1.3.2,
    1.4.7, 1.5.2 and 1.6.4 — and correctly found nothing on 1.2.5, because 1.3.1
    is where Mojang added the encryption handshake. Before that there is no
    getKeyPair, no encryption, and no branch worth forcing.

    13/13 jars now pass the real JVM bytecode verifier, spanning twelve years of
    Minecraft.

    Better Than Wolves: CE

    BTWCE is an unusual stack: Minecraft 1.6.4 on Legacy Fabric, running on
    Java 17–21 because it depends on GrossFabricHacks. It works drop-in, with
    all 12 of its mods loaded:

    alice -> AUTHENTICATE  serverId="-2bdbb7bf5b42fe41"
    bob   -> NO_AUTH       serverId="-"
    patched net/minecraft/class_801.method_1861
            (gate MinecraftServer.method_2984()Z, username in field_2888)
    

    Reproduce the whole stack with poc/setup-legacy.ps1. It must run on Java 17 —
    BTWCE rejects Java 8 outright at mod resolution.

    What pre-1.7 does differently

    • Pre-netty protocol. No VarInts, strings are length-prefixed UTF-16BE,
      different packet ids. poc/src/LegacyProbeClient.java speaks it.
    • Different discriminator. The server sends an encryption request either
      way
      — encryption is not optional there. Intent is carried by the serverId
      inside it: a real hash means "verify with Mojang", "-" means "don't bother".
    • Auth goes to session.minecraft.net/checkserver.jsp, not authlib. That
      endpoint is still live, which is why selective auth is still meaningful on
      these versions.
    • No UUIDs exist. authlib arrived in 1.7.2; before that a player simply is
      their username.

    Changes

    Added the preLaunch Fabric entrypoint. This is what made it work at all.
    main and server are invoked through a hook the game provider injects into
    Minecraft's own startup, and Legacy Fabric's 1.6.4 provider injects neither on a
    dedicated server — the mod loaded, appeared in the mod list, and silently did
    nothing. preLaunch is invoked by Knot itself, so it fires on every Fabric
    variant, and it is the better moment regardless: it runs before any Minecraft
    class is defined. Modern Fabric now uses it too, with no regression.

    uuid-mode and skins-for-unauthenticated now warn on pre-1.7 servers. They
    already degraded to no-ops, but silently. The server now says plainly that they
    have nothing to act on, the same way it already warns about
    enforce-secure-profile. Selective authentication and reserve-premium-names
    work normally there.

    New tooling: poc/src/LegacyProbeClient.java (pre-1.7 login probe),
    poc/src/StringScan.java (works out how a given version talks to Mojang),
    poc/setup-legacy.ps1 (installs Legacy Fabric + BTWCE end to end).

    Unchanged

    Everything from 0.1.0 still passes: both modes, all three uuid-mode values,
    skins, reserve-premium-names, hot reload, and the imposter test. Verified live
    on Forge 1.12.2, Forge 1.20.1, NeoForge 1.21.1, Fabric 1.20.1, vanilla 1.21.1 and
    now Legacy Fabric 1.6.4 — six platforms, five naming schemes.

    Downloads
  • v0.1.0 b787485a72

    NetworkChorus released this 2026-07-26 15:38:40 +00:00 | 3 commits to main since this release

    Per-player authentication for Minecraft servers. Instead of one server-wide
    online-mode switch, you choose exactly which usernames are verified against
    Mojang.

    • EXCLUDE — the server runs offline, and only the names you list are pushed
      through Mojang authentication. They alone get verified identities and skins.
    • INCLUDE — the server runs online, and every name is authenticated except
      the ones you list.

    Server-side only. No client mod — the client simply answers whatever the
    server asks it.

    One jar, every loader

    selectiveauth-0.1.0.jar (~57 KB) is the entire download. It carries
    mcmod.info, mods.toml, neoforge.mods.toml and fabric.mod.json at once;
    each loader finds its own and ignores the rest.

    Verified running on five platforms and four naming schemes:

    platform naming delivery
    Forge 1.12.2 (Java 8 JRE) SRG LaunchWrapper tweaker
    Forge 1.20.1 SRG self-attach
    NeoForge 1.21.1 Mojang self-attach
    Fabric 1.20.1 intermediary self-attach
    vanilla 1.21.1 obfuscated -javaagent

    Patches are additionally checked against the real JVM bytecode verifier on
    nine server jars spanning 1.7.10 → 1.21.5.

    Install

    Recommended, always works:

    java -javaagent:selectiveauth-0.1.0.jar -jar server.jar nogui
    

    Or drop it in mods/ — it self-attaches. On Forge 1.7.10–1.12.2 it registers as
    a LaunchWrapper tweaker instead, so drop-in works there even on a JRE with no
    tools.jar.

    JEP 451: a future JDK will disallow dynamic agent loading by default. When
    that lands, drop-in mode will need -XX:+EnableDynamicAgentLoading; the
    -javaagent form is unaffected.

    Configure

    selectiveauth.properties, in config/ if it exists, otherwise the server
    directory. Edits apply within ~2 seconds — no restart (except uuid-mode).

    mode=EXCLUDE
    names=alice,bob
    enabled=true
    
    uuid-mode=NATIVE
    skins-for-unauthenticated=false
    reserve-premium-names=false
    

    uuid-mode

    value authenticated player unverified player
    NATIVE real Mojang UUID offline hash
    FORCE_OFFLINE offline hash, real skin kept offline hash
    FORCE_ONLINE real Mojang UUID real Mojang UUID of that name

    NATIVE is vanilla behaviour, and its sharp edge is that moving a name between
    lists changes that player's UUID — new inventory, new advancements, dropped
    op/whitelist entries. FORCE_OFFLINE removes that edge: identity stays put
    however you edit the list, and verified players still get their real skin.

    FORCE_ONLINE is dangerous and off by default — it lets an unverified client
    inherit a real account's playerdata just by typing their name. Whitelist only.

    Read this before you file a bug

    enforce-secure-profile must be false on 1.19+. An unauthenticated player
    has no Mojang profile key, cannot sign chat, and is disconnected during login no
    matter what this mod does. SelectiveAuth warns loudly at startup if it sees this
    combination, because the symptom is indistinguishable from "the mod didn't work".

    Turn on reserve-premium-names if you run EXCLUDE mode publicly. Otherwise an
    unverified client can claim any name that is not on your list, including a real
    account's.

    Behind a proxy (Velocity, BungeeCord), authentication happens at the proxy, so
    this belongs there instead — it will do nothing useful on a backend server.

    Antivirus may flag a jar that self-attaches an agent. That is inherent to the
    one-jar design.

    How it works

    Four ideas, in case you want to audit it rather than trust it:

    1. Structural fingerprinting. The auth branch is found by shape — a method
      invoking something that returns java.security.KeyPair, branching on a no-arg
      ()Z call on that same receiver. KeyPair is a JDK type, so the descriptor
      survives every remapping scheme. No mappings, no refmaps, no per-version
      builds.
    2. Length-preserving patches. 7 bytes for 7, 3 for 3, 5 for 3+2 NOP. Stack
      depth and the StackMapTable stay valid, so nothing needs recomputing — and
      there is no ASM at runtime, which matters because ASM refuses class files
      newer than itself and would break on Minecraft versions that don't exist yet.
    3. A java agent, so no loader-specific transformer API is ever touched. This
      also handles Forge 1.7–1.12, which rewrites Minecraft at runtime where a
      disk-based patcher would see nothing.
    4. Bridge methods injected into Minecraft's own classes, so authlib types
      resolve in the loader that can see them and our code never names one. This is
      what makes uuid-mode and skins work on vanilla, where Minecraft keeps its
      libraries in a child class loader.

    Every failure path falls back to exactly what vanilla would have done. If the
    fingerprint doesn't match, if reflection fails, if the username can't be read —
    the server behaves as its online-mode dictates and says so in the log. A broken
    install is a no-op, never a locked-out server.

    Verified

    Selective auth, EXCLUDE + INCLUDE live on 5 platforms
    uuid-mode × 3 verified, FORCE_OFFLINE with a real account
    skins-for-unauthenticated live, real signed textures
    reserve-premium-names verified against the live Mojang API
    hot config reload live
    imposter refused live — valid crypto, no Mojang session → rejected
    patch + JVM verifier 9/9 jars
    behavioural suite 8/8

    Not tested: Paper and Velocity.

    Known limitation

    uuid-mode changes take effect at server start, not on config reload — the
    authenticated-path patch is only installed when FORCE_OFFLINE is set at
    startup, so the default configuration carries no risk it doesn't use.

    Downloads