dwgx@blog:~$dwgx
> cd ../posts

l2111pageloginverify: A local login verification plugin I wrote for an MC private server

// created

l2111pageloginverify is a local login verification plugin for Paper 1.21 servers. It runs on a private server I set up with friends. No third-party account system, no external authentication. Usernames and passwords all run locally, and the data stays in your own hands.

An MC server has no native input UI. The common approach is to have players type /login password in chat, which puts the plaintext right there in the chat box. This plugin uses signed books instead: a player joining the server is locked down, handed a verification book, fills in a username and password, and signs it. Signing automatically registers or logs them in. A signed book can’t be edited and leaves no draft, so the chat box stays clean. Until verification passes, the player is fully frozen. Movement, interaction, chat, commands, inventory, and taking damage are all blocked. If the inventory is full and needs room, items are first stashed safely, then returned exactly as they were once verification completes, preserving NBT, enchantments, and durability.

User data lands in users.yml. Passwords support both plaintext and PBKDF2 hashed modes, switchable at runtime with /dwgxverify encryption <true|false>. The data is partitioned into data.hashed and data.plain so the two never contaminate each other. Every login writes a record into logs.yml with IP, timestamp, and its own separate salt. There’s also login rate limiting, an input length cap, a kick if the book isn’t signed before timeout, and an admin review mode: with it enabled, registration requires /dwgxverify approve to go through.

Managing everything from the command line is a hassle, so I added a local web panel while I was at it. It listens on http://127.0.0.1:1337 by default, bound to localhost only. It shows the user list, search with pagination, review, reset handling, and config switching. Sticking to zero external dependencies, the pages are assembled purely in Java with no HTML, and the plugin works as soon as you drop it into plugins/. The panel uses Basic Auth with a default password of change-me. Remember to change it before going live.

Built with Java 21 and Gradle 8.8, debugged against a local 1.21 test server spun up via run-paper. The paper-api version is 1.21.11-R0.1-SNAPSHOT, current version 1.0-SNAPSHOT, tweaked on the fly as I use it myself.