• 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