Skip to content

Releases: samupro-dev/LibreLoginNext

Release list

0.26.0

Choose a tag to compare

@samupro-dev samupro-dev released this 24 Oct 19:04

Changelog

Added

  • Added a standalone :Lettuce Gradle subproject (Libraries/Lettuce) bundling io.lettuce:lettuce-core:7.9.0.RELEASE with a private, relocated copy of Netty 4.2 (xyz.kyngs.librelogin.lib.netty) and Project Reactor (xyz.kyngs.librelogin.lib.reactor) to avoid conflicts with the server's Netty 4.1 runtime while excluding native Netty transport binaries.
  • Added RedisService to manage the native Lettuce Redis client lifecycle, RESP3 protocol negotiation, decorrelated-jitter auto-reconnection, connection state monitoring, and unique cluster node identification (node-<uuid>).
  • Added RedisPresenceProvider for cluster-wide online player presence tracking (librelogin:player:<uuid> and librelogin:node:<serverId>:players) backed by atomic Lua scripts (DELETE_IF_OWNER and REFRESH_IF_FREE_OR_OWNER) and pipelined heartbeats so disconnecting or shutting-down nodes never delete presence keys owned by another proxy.
  • Added RedisPubSubHandler on channel librelogin:sync:events to broadcast cross-proxy user cache invalidations (INVALIDATE_USER) and remote player kicks (REMOTE_KICK) with localized message key resolution (key:<messageKey>) or Base64URL-encoded custom text.
  • Added a standalone :Adventure Gradle subproject (Libraries/Adventure) bundling and relocating Kyori Adventure 4.26.1 (adventure-api, adventure-text-minimessage, adventure-text-serializer-legacy, adventure-text-serializer-plain, adventure-text-serializer-gson) under xyz.kyngs.librelogin.lib.adventure.
  • Added ComponentBridge and PlatformAudience to serialize relocated Adventure components with JSONOptions.compatibility() (emitting both legacy camelCase and modern snake_case click/hover event keys) and legacy section-sign formatting with optional 1.16+ RGB hex (§x§r§r§g§g§b§b) support.
  • Added PaperAdventure, PaperNativeAdventure, and PaperAudience to bridge relocated Adventure components to Paper's native Adventure API on Paper 1.16.5+ or legacy Bukkit/Spigot/BungeeChat APIs on Paper 1.13.2–1.16.4 with runtime capability detection and LinkageError fallbacks.
  • Added VelocityAudience to bridge relocated Adventure components with Velocity's native Adventure Audience and Title APIs.
  • Added PBKDF2CryptoProvider (PBKDF2 algorithm identifier, PBKDF2-HMAC-SHA256 with 310,000 iterations and 256-bit derived key length) backed by Password4j.
  • Added SCryptCryptoProvider (SCrypt algorithm identifier, configured with OWASP parameters N=16384, r=8, p=1, dkLen=32) backed by Password4j.
  • Added VerifyOnlyCryptoProvider and LegacyMessageDigestCryptoProvider (SHA-256, SHA-512, LOGIT-SHA-256) to verify imported legacy password hashes without allowing them as the default hashing algorithm, automatically re-hashing verified passwords with the default provider upon login.
  • Added LegacyHashNormalizer to convert legacy split hash/salt database representations (BCrypt-2A/2B/2X/2Y, Argon-2ID) and AuthMe $SHA$<salt>$<hash> strings into standard Modular Crypt Format (MCF) hashes with salt = null.
  • Added psw4j.properties (global.salt.length=64) to explicitly configure Password4j's default 64-byte salt length.
  • Added CryptoUtil.hmacSha256(String, String) and AuthenticLibreLogin.anonymizeIP(String) to support HMAC-SHA256 IP address hashing when privacy.ip-storage-mode is set to HASHED, alongside CryptoUtil.wipe(char[]) and CryptoUtil.wipe(byte[]) to zero-fill sensitive arrays in memory.
  • Added GeneralUtil.isValidEmail(String), GeneralUtil.escapeHtml(String), GeneralUtil.translateLegacyToMiniMessage(String), and GeneralUtil.userAgent(String).
  • Added /unregister <password> (UnregisterCommand, permission librelogin.command.unregister), gated by allow-player-unregister, allowing authenticated players to verify their password, clear their credentials/2FA/email, and unregister their own account.
  • Added /cracked [password] [passwordRepeat] (CrackedCommand and AbstractPremiumCommand, permission librelogin.command.cracked), requiring unregistered premium players to set a password before switching to cracked mode so the account cannot be left unclaimed.
  • Added /2fa disable <password> in TwoFactorCommand allowing authenticated players to disable 2FA after verifying their password, and added manual TOTP secret key chat output (totp.show-info-manual, totp.secret-key) when map projection is unavailable or fails.
  • Added /librelogin health (librelogin.admin.health) to display platform name and version, JVM heap usage, database connectivity and connector type, and cached user count (getCachedUsersCount()).
  • Added /librelogin reload (librelogin.admin.reload) to reload config.conf, messages.conf, backend server tables (AuthenticServerHandler.reload()), forbidden password lists (loadForbiddenPasswords()), and ACF command locales in a single command.
  • Added /librelogin user forget <player> (librelogin.admin.user.forget) to kick the target player if online and permanently delete their user record from the database.
  • Added LibreLoginSQLMigrateReadProvider (librelogin-migration-mysql, librelogin-migration-postgresql, librelogin-migration-sqlite) supporting multi-dialect column aliases, second-to-millisecond timestamp conversion, and legacy hash normalization when migrating from existing LibreLogin databases.
  • Added LoginToSQLMigrateReadProvider (loginto-mysql, loginto-sqlite) to migrate player accounts from LoginTo (LoginTo_Players_Accounts), aborting migration if nameless rows or unsupported password hashes are detected.
  • Added a one-time migration.done marker file in GeneralUtil.checkAndMigrate so configured database migrations run only once and do not overwrite accounts on subsequent server restarts.
  • Added SQLMigrateReadProvider.getEscapedTableName() to safely quote SQL table identifiers for PostgreSQL ("...") and MySQL/SQLite (`...`).
  • Added a database connectivity circuit breaker (MAX_CONSECUTIVE_FAILURES = 3) and half-open recovery prober (PROBE_INTERVAL_MILLIS = 5000, connection.isValid(2)) in AuthenticDatabaseConnector, with isStatementError filtering so SQL constraint or syntax errors (SQLState classes 23 and 42) do not trip the connectivity breaker.
  • Added AuthenticDatabaseConnector.keepaliveFor(long) to compute a HikariCP keepaliveTime scaled to maxLifetime (or disabled when maxLifetime / 2 < 30000 ms).
  • Added three bounded Caffeine user lookup caches (userByUuidCache, userByNameCache, userByPremiumUuidCache, max 10,000 entries) in LibreLoginSQLDatabaseProvider with dynamic expiry (5 minutes when Redis is active, 30 seconds standalone) and cross-proxy invalidation broadcasts.
  • Added transactional user archiving (archiveUser) in LibreLoginSQLDatabaseProvider to copy overwritten profile-conflict accounts into librepremium_data_archive with an archived_at timestamp before deleting them from librepremium_data.
  • Added batched database cleanup methods purgeInactiveUsers(int days) and purgeAbandonedUsers(int days) (deleting in batches of 500) in LibreLoginSQLDatabaseProvider, scheduled at startup in AuthenticLibreLogin to purge inactive accounts (privacy.auto-purge-inactive-days) and unregistered pre-login reservations older than 7 days.
  • Added database schema indexes ip_index on librepremium_data(ip), last_seen_index on librepremium_data(last_seen), and last_nickname_lower_index on LOWER(last_nickname) (for PostgreSQL and SQLite), plus automatic case-insensitive collation detection (detectCaseInsensitiveNickname) in LibreLoginMySQLDatabaseProvider.
  • Added ConfigurationValidator to validate config.conf on load and reload, checking default-crypto-provider (rejecting unknown or verify-only providers), new-uuid-creator, profile-conflict-resolution-strategy, non-empty allowed-commands-while-unauthorized, numeric bounds, port ranges, and redis.key-ttl-seconds > redis.heartbeat-interval-seconds.
  • Added new configuration keys in ConfigurationKeys: forbidden-passwords-download, password-regex, require-password-confirmation, allow-player-unregister, check-for-updates, login-security.max-ip-login-attempts, login-security.ip-attempts-expire-millis, privacy.ip-storage-mode, privacy.ip-hash-salt, privacy.auto-purge-inactive-days, redis.enabled, redis.host, redis.port, redis.username, redis.password, redis.database, redis.ssl, redis.timeout-ms, redis.heartbeat-interval-seconds, redis.key-ttl-seconds, database.properties.mysql/postgresql.pool-size, connection-timeout, leak-detection-threshold, and database.properties.postgresql.sslmode.
  • Added new message keys in MessageKeys covering database/internal/session/rate-limit/remote/shutdown kicks (kick.*), command/2FA/email/lockout errors (error.*), health diagnostics (health.*), manual TOTP setup (totp.show-info-manual, totp.secret-key, totp.already-enabled, totp.unavailable), localized /librelogin user info values (info.value-na, info.value-enabled, info.value-disabled, info.alts-more, info.2fa-disabled, info.user-forgotten, info.kick-unknown-reason), test email templates (email.test-subject, email.test-content), and updated command syntax/autocomplete entries.
  • Added pre-login per-IP connection rate limiting (preLoginAttempts, max 8 attempts per 10-second window per non-loopback IP) and zero-allocation character-by-character username validation (isValidMinecraftUsername) in AuthenticListeners.
  • Added per-IP failed login tracking (loginTriesByIp) and exponentially escalating per-account lockouts (lockouts, 30-second base duration doubling up to 15 minutes) in LoginTryListener.
  • Added TOTP time-slot replay protection (usedTimesteps cache enforcing strictly increasing time slots per secret) and a 5-...
Read more