VeloAuth
Complete Velocity authentication plugin with intelligent nickname protection, premium auto-login, secure offline player management, and optional self-contained embedded limbo.
What is VeloAuth?
VeloAuth is a comprehensive authentication system for Velocity proxy that handles all player authorization before they reach your backend servers. It includes a loopback-only embedded limbo while maintaining full compatibility with existing external limbo servers, all while protecting nickname ownership through intelligent conflict resolution.
Live test server
Want to see VeloAuth in action? 2b2t.pl runs the plugin in production — join the server to test premium auto-login, offline registration and nickname protection on a live network.
Key Features
- 🔒 Intelligent Nickname Protection - Premium nicknames are reserved unless already registered by cracked players.
- ⚡ Premium Auto-Login - Mojang account owners skip password entry after session verification; auth/limbo passthrough is an opt-in bypass.
- 🔄 Automatic Nickname Change Detection - Detects when a premium player renames their Mojang account and updates the database record automatically.
- 🛡️ Secure Offline Auth - BCrypt password hashing, brute-force protection, and atomic first-owner registration enforced by the database.
- 📱 Optional Floodgate Support - Bedrock and linked Floodgate accounts are detected before Mojang resolution; only UUIDs confirmed by Floodgate can bypass the auth server.
- 🧩 Optional Self-Contained Limbo - Use the built-in 1.8-base limbo with a reviewed, checksum-pinned ViaVersion runtime, or keep using an external limbo (NanoLimbo, etc.).
- 🗺️ Forced Hosts Support - Players connect via custom domains (e.g.,
pvp.server.com) and are properly routed to their intended server after authentication. - 🚫 Smart Command Hiding - Authentication commands (
/login,/register) are hidden while authorization is active; expired sessions expose them again. - 🚀 High Performance - Bounded three-layer premium cache (in-memory → DB → Mojang/Ashcon API), virtual threads (Java 21), and zero blocking on Velocity event loops.
- 🔐 Optional 2FA (TOTP) - Opt-in RFC 6238 second factor compatible with Google Authenticator, Authy, Aegis. See 2FA.md for the operator handbook.
- 🔄 Conflict Resolution - Smart handling of premium/cracked nickname conflicts with
/vauth conflicts. - 📊 Admin & Diagnostic Tools - Health checks, statistics, and 1-click sanitized diagnostic reports via
/vauth report(mclo.gs). - 🗄️ Multi-Database - MySQL, PostgreSQL, H2, and SQLite with HikariCP connection pooling.
- 🌍 17 Languages & HEX Formatting - EN, PL, DE, FR, RU, TR, SI, FI, ZH_CN, ZH_HK, JA, HI, VI, KO, TH, ID, PT_BR with full RGB/HEX color support.
- 🔄 LimboAuth Compatible - 100% database schema compatibility with automatic, additive in-place migrations.
- 📢 Discord Alerts - Webhook notifications for security anomalies and resolver failure spikes with automated retry logic.
When to use VeloAuth
- You run a Velocity proxy with one or more backend servers and need authentication at the proxy layer (not per-backend).
- You accept both premium and cracked players and need automatic, fail-secure routing — premium players skip
/login, cracked players go through BCrypt-hashed registration. - You already use LimboAuth and want to migrate without losing data — VeloAuth reads and upgrades the same schema seamlessly.
- You want high performance — premium status is resolved through a three-layer cache without blocking proxy event loops.
If you only run a single backend server (Paper/Spigot/Folia) without a proxy, use a backend-side auth plugin instead.
Operating Profiles
Choose how strict nickname protection should be in plugins/veloauth/config.yml:
Profile 1 — Mixed strict (default, recommended)
premium:
check-enabled: true
allow-cracked-on-premium-nicks: false
bypass-auth-server: false
- What you get: Premium players auto-login with real Mojang UUIDs; cracked players go through
/register+ BCrypt; premium nicknames are strictly reserved for Mojang owners. - What you lose: Cracked clients trying to join with a registered Mojang username are rejected ("You are not logged into your Minecraft account").
- Best for: Public servers accepting both types of players where nickname theft prevention matters.
Profile 2 — Cracked-only
premium:
check-enabled: false
- What you get: Zero HTTP traffic to Mojang/Ashcon, deterministic offline UUIDs for everyone.
- What you lose: Premium auto-login is disabled for all players; first player to register a nickname owns it.
- Best for: Private networks, dev environments, or pure offline-mode setups.
Profile 3 — Permissive mixed
premium:
check-enabled: true
allow-cracked-on-premium-nicks: true
- What you get: Existing premium accounts retain premium UUIDs; cracked players can register unclaimed premium-looking usernames.
- What you lose: New premium players connecting for the first time receive offline UUIDs permanently if not pre-registered as premium.
- Best for: Cracked-first communities that prioritize admitting all players without kick screens.
| Goal | Recommended Profile |
|---|---|
| Maximum security, premium UUIDs preserved | 1 — Mixed strict |
| No Mojang calls, pure offline network | 2 — Cracked-only |
| Accept all connections, unreserved nicknames | 3 — Permissive mixed |
Requirements
- Java 21 or newer (tested on Temurin 21)
- Velocity Proxy (3.4.0+ / 3.5.x line)
- Database: MySQL, PostgreSQL, H2 (default), or SQLite
- Auth Server Topology:
- External (default): NanoLimbo, LOOHP/Limbo, LimboService, PicoLimbo, or similar.
- Embedded (optional): Built-in 1.8 loopback limbo (requires outbound HTTPS to ViaVersion maven repo for runtime staging).
Quick Setup
1. Installation
- Download the latest
veloauth-X.X.X.jarfrom Modrinth. - Drop it into your Velocity
plugins/folder. - Start and stop Velocity to generate configuration files in
plugins/veloauth/. - Configure database details and auth settings in
plugins/veloauth/config.yml. - Start Velocity.
2. Velocity Configuration (velocity.toml)
[servers]
limbo = "127.0.0.1:25566" # External limbo server (keep out of try list!)
lobby = "127.0.0.1:25565" # Primary backend lobby
survival = "127.0.0.1:25567" # Secondary backend server
try = ["lobby", "survival"] # Fallback backend order for authenticated players
[forced-hosts]
# Players joining via survival.example.com authenticate in limbo,
# then get routed directly to 'survival' instead of 'lobby'.
"survival.example.com" = ["survival"]
3. VeloAuth Configuration (plugins/veloauth/config.yml)
language: en
auth-server:
# 'external' (default) uses registered limbo server; 'embedded' starts loopback limbo.
mode: external
server-name: limbo
timeout-seconds: 300
embedded:
port: 0 # 0 = auto-select loopback port
max-connections: 512
handshake-timeout-seconds: 10
login-timeout-seconds: 15
premium:
check-enabled: true
allow-cracked-on-premium-nicks: false
# Set to true only if verified premium players should skip the auth-server completely
bypass-auth-server: false
# Optional Floodgate integration
floodgate:
enabled: false
username-prefix: "."
bypass-auth-server: true
Password Complexity Policy (Optional)
security:
min-password-length: 8
max-password-length: 72
password-policy:
min-digits: 0 # e.g., 1 = require at least one digit
min-uppercase: 0 # e.g., 1 = require at least one uppercase letter
min-lowercase: 0 # e.g., 1 = require at least one lowercase letter
min-special: 0 # e.g., 1 = require at least one symbol
Commands & Permissions
Player Commands
| Command | Description | Notes |
|---|---|---|
/register <password> <confirm> |
Register a new account | Hidden once logged in |
/login <password> |
Log into your account | Available in auth/limbo |
/logout |
Invalidate session & disconnect | Clean disconnect; requires /login upon return |
/changepassword <old> <new> |
Update your account password | Requires active session |
/2fa setup |
Begin TOTP authenticator setup | Requires active session |
/2fa verify <code> |
Confirm TOTP setup or submit 2FA code | Standard RFC 6238 TOTP |
/2fa disable <code> |
Remove 2FA from account | Requires valid TOTP code |
/2fa qr / /2fa status |
Show 2FA enrollment status | Re-enrollment instructions |
Admin Commands (veloauth.admin)
| Command | Description |
|---|---|
/vauth reload |
Reload configuration & language files |
/vauth report |
Upload sanitized diagnostic bundle to mclo.gs |
/vauth stats |
Show runtime cache, thread, and connection stats |
/vauth conflicts |
List active nickname ownership conflicts |
/vauth cache-reset [player] |
Clear premium resolver/auth caches |
/vauth 2fa-remove <nickname> |
Administrative 2FA reset for recovery |
/unregister <nickname> |
Delete account record from database |
LimboAuth Migration
VeloAuth features 100% automatic LimboAuth schema migration:
- Stop LimboAuth on your backend servers.
- Install VeloAuth on your Velocity proxy.
- Configure
plugins/veloauth/config.ymlwith the same database credentials. - Start Velocity. Existing accounts and
/premiumflags will be converted seamlessly on startup without manual UUID rewrites.
Links & Support
- Source Code & Releases: GitHub Repository
- Issue Tracker: GitHub Issues
- Community & Support: Discord Server
- Documentation: 2FA Guide | Changelog
- License: MIT
All Versions
+ Add Version### Added
- Automatic auth message language detection based on the Minecraft client locale (
detect-client-language).
### Fixed
- Auth reminders now show
/loginor/registerbased on account status. - Session expiry is enforced before automatic backend transfers.
- Premium
UNKNOWNresults are no longer cached as non-premium. - Added a Minecraft Services fallback when the Mojang API is unavailable.
hit-ttl-minutes: 0now correctly disables premium cache lookups.- Fixed concurrent database initialization, SQLite migration guards, and database shutdown handling.
### Security
- MySQL defaults to TLS with server identity verification unless SSL is explicitly configured.
- Authentication command arguments are redacted from diagnostic reports.
- Safer processing of long log lines.
### Changed
- Updated dependencies and build tools.
- Fixed**
- Players could miss the register/login instructions on the auth server (#48).
database lookup falls back to the generic prompt instead of silence.
- H2/SQLite database files were created in the proxy root (
data/) instead of
plugins/veloauth/data/ — existingfiles are migrated automatically and safely (never deleted or overwritten).
- Notes**
- No changes for MySQL/PostgreSQL setups.
- 🔒 Security fix.** Premium players connecting during the startup window — after Velocity opens
got an offline UUID on proxies with
online-mode = false. The window reopened on every restartand could be timed deliberately: treat it as a name-sniping vector. Queued logins now go through
the full PreLogin pipeline, and are denied if it isn't ready.
- ⏱️ Rate limits for premium lookups.** A join wave could multiply into far more upstream requests
under
premium.resolver: mojang-requests-per-minute (120), ashcon- / wpme-requests-per-minute(60),
rate-limit-max-wait-ms (1000). Set to 0 to disable.- Upgrading.**
A major update focused on the new embedded auth/limbo system, stability and security.
### Highlights
- Added
/logoutcommand - Added optional premium-player auth server bypass
- Added built-in embedded auth/limbo with Minecraft 1.8–26.2 support
- Improved embedded limbo compatibility with modern clients and Velocity forwarding
- Fixed Minecraft 1.8 keepalive and modern-client loading issues
- Improved backend routing and prevented duplicate connection attempts
- Added embedded runtime diagnostics to
/vauth report - Added privacy-safe bStats metrics
- Improved shutdown, reconnect and async task handling
- Multiple runtime verification and security hardening improvements
### Important
- Requires **Java 21** and **Velocity 3.5-compatible API**
- Full proxy restart required after updating
- Default automatic transfer delay is now **1500ms**
This release focuses on security, compatibility, and message customization.
- Added complete HEX color support for all player-facing messages.
- Improved premium/cracked account handling and LimboAuth compatibility.
- Hardened session cleanup, duplicate connections, and premium lookup limits.
- Improved 2FA security and prevented enrolled secrets from being exposed again.
- Made diagnostic reports privacy-safe by default with opt-in log uploads.
- Added extensive regression tests and general stability fixes.
## 🚀 Features
- VeloAuth & Auth:** Bumped to
v1.3.1with command refactoring, premium auth improvements (4c8a727), and addedallow-cracked-on-premium-nicksconfig (b14c2e5). - 2FA / TOTP:** Implemented TOTP service (
05c1347) with clickable QR links (3a852f6,6d741c3). Enhanced privacy by switching tobase32secrets in URLs (de4c205) and simplified the logic by hardcoding the QR endpoint (a7b5608).
## ⚙️ Refactoring & Fixes
- Database & Logs:** Refactored DB management, improved TOTP replay protection (
fca09e7), and renamedrecordtosaveinAuditLogServicefor consistency (0b588d2). - Cleanups:** Removed ASCII QR rendering and its dependencies (
6d741c3). Hardcoded shutdown/closed messages to English to prevent encoding issues (f9780f0).
- Password complexity policy.** New optional
security.password-policysection inconfig.ymlwithmin-digits,min-uppercase,min-lowercase,min-specialcounters. All default to0(= no constraint), so existing configs keep working unchanged. - Discord webhook alerts are now wired.** `. Previously the service existed but was never instantiated.
- Kick-reason logs are now readable.**
- Translation updates**
- Fixes**
09916dd feat: introduce ListenerFactory for listener instantiation and integrate IPRateLimiter cleanup into AuthCache (rafalohaki)
e4e5573 refactor: Encapsulate internal database components by reducing visibility and simplify virtual thread executor management. (rafalohaki)
f2fed46 feat: make premium resolver more resilient by accepting both 204 and 404 for not-found responses and prioritizing explicit offline results over unknown resolver states. (rafalohaki)
4f14efa feat: Enhance brute force protection by tracking failed login attempts per username (rafalohaki)
d2d4ece Add unit and integration tests for database and authentication components (rafalohaki)
964bc85 feat: add command in progress message and improve premium detection logic (rafalohaki)
ea37746 refactor: update dependency injection to use Jakarta and improve initialization handling in VeloAuth and AuthListener (rafalohaki)
6aff115 Fix: Prevent premium player UUID corruption by denying pre-login on database errors, update Velocity API, and add a new 'waiting for server' localization message. (rafalohaki)
- More languages support
- Comprehensive Floodgate/Bedrock support with Geyser integration
### 🔧 Improvements
- Complete configuration management overhaul with SettingsLoader
- Enhanced Discord webhook URL validation
- Improved credential handling and password key definitions
- Virtual thread execution for conflict handling and better performance
- Enhanced error handling across all components
- Better bcrypt cost and language code validation
- Dynamic IP rate limiting settings
- Async IO operations for improved responsiveness
### 🐛 Bug Fixes
- Enhanced Floodgate username prefix validation and logging
- Improved premium detection logic in AuthListener
- Better database health check and connection management
- Fixed HTTP JSON client parsing and numeric string conversion
- Improved thread safety with AtomicInteger for brute force tracking
- Enhanced error message constants and formatting
- Fixed nickname conflict resolution in PreLoginHandler
- Better UUID verification with runtime exception handling
- c3371d9 build**: update HikariCP, Jackson, and JUnit dependency versions. (rafalohaki)
- 20dee59 update instructions** (rafalohaki)
- 05cdd6f feat**: Implement asynchronous premium resolution during
- d84f1fc version update** (rafalohaki)
- 6d66e1a fix typo (rafalohaki)
- 89f773e feat: Implement Mojang API failure handling and advanced nickname conflict resolution using UUIDs to prevent name sniping. (rafalohaki)
- 426883d feat: Introduce configurable session inactivity timeout and enhance login and cache management robustness. (rafalohaki)
- ca6c940 Merge pull request #10 from rafalohaki/snyk-upgrade-e534f8f3500dbc96aceb8d2e19fe8747 (rafalohaki)
- 53afcbe . (rafalohaki)
- 97f0985 . (rafalohaki)
- 0620904 update rules (rafalohaki)
- 1ac55a9 fix: upgrade org.postgresql:postgresql from 42.7.8 to 42.7.9 (snyk-bot)
small translation changes
delete lang folder to regenerate new
please regenerate lang folder
cleanup code
I was using mainly postgres, my fault i didnt test h2
quality fixes