System Architecture
Relevant source files
The following files were used as context for generating this wiki page:
- API/src/main/java/xyz/xreatlabs/nexauth/api/NexAuthPlugin.java
- Plugin/src/main/java/xyz/xreatlabs/nexauth/common/AuthenticNexAuth.java
- Plugin/src/main/java/xyz/xreatlabs/nexauth/paper/PaperPlatformHandle.java
- Plugin/src/main/java/xyz/xreatlabs/nexauth/velocity/VelocityPlatformHandle.java
- Plugin/src/main/java/xyz/xreatlabs/nexauth/common/config/ConfigurationKeys.java
- Plugin/src/main/java/xyz/xreatlabs/nexauth/paper/PaperBootstrap.java
- Plugin/src/main/java/xyz/xreatlabs/nexauth/velocity/VelocityNexAuth.java
- Plugin/src/main/java/xyz/xreatlabs/nexauth/common/config/ConfigurateConfiguration.java
- Plugin/src/main/java/xyz/xreatlabs/nexauth/common/database/AuthenticUser.java
NexAuth is a multi-platform authentication plugin for Minecraft servers, designed with a modular and extensible architecture. It supports various server platforms like Paper, Velocity, and BungeeCord by separating common logic from platform-specific implementations. The core of the system provides robust features such as database management, cryptography, configuration handling, and player authentication flows, while platform-specific modules handle direct server interactions.
The architecture is centered around a common AuthenticNexAuth class, which contains the bulk of the plugin's logic. This core is supported by a PlatformHandle interface that abstracts away the differences between server environments. This design allows for consistent behavior across all supported platforms while enabling platform-native features and integrations, such as the use of NexLimbo for a secure authentication environment.
Core Components
The system is composed of several key components that work together to provide the authentication service. The main architectural pattern is the separation of a common, platform-agnostic core from specific platform implementations.
This diagram shows the high-level relationship between the core components and platform-specific modules.
AuthenticNexAuth
The AuthenticNexAuth<P, S> class is the abstract heart of the plugin. It contains the shared logic for all supported platforms, including:
- Lifecycle Management: The
enable()anddisable()methods orchestrate the plugin's startup and shutdown sequences. - Configuration Loading: Manages loading
config.ymlandmessages.ymlusing theHoconPluginConfigurationandHoconMessagesclasses. - Database Management: Handles database connections, schema validation, and data migration. It allows for different database backends (MySQL, PostgreSQL, SQLite) to be registered and used.
- Provider Registries: Maintains registries for
CryptoProviderandReadDatabaseProvider, making the system extensible. - Core Services: Initializes and provides access to core services like
AuthorizationProvider,PremiumProvider,TOTPProvider, andEmailHandler. - Integrations: Manages integrations with other plugins like Floodgate and LuckPerms.
Sources: AuthenticNexAuth.java:115-121, 218-285, 335-475
NexAuthPlugin API
The NexAuthPlugin<P, S> interface defines the public API for NexAuth. It exposes core functionalities to other plugins or modules, ensuring a stable contract for interaction. Key methods include:
getPremiumProvider()getDatabaseProvider()getCryptoProvider(String id)getPlatformHandle()registerReadProvider(...)registerCryptoProvider(...)
Sources: NexAuthPlugin.java
Platform Abstraction
A key architectural decision is the use of the PlatformHandle<P, S> interface to abstract platform-specific operations. This allows the AuthenticNexAuth core to remain independent of any specific Minecraft server software (like Paper or Velocity).
PlatformHandle Interface
This interface defines a contract for actions that differ between platforms, such as:
movePlayer(P player, S to): Teleporting a player to a server or world.kick(P player, Component reason): Kicking a player from the network.getServer(String name, boolean limbo): Retrieving a server or world instance.getIP(P player): Getting a player's IP address.
Sources: PaperPlatformHandle.java:25-50, VelocityPlatformHandle.java:31-56
Class Diagram: Platform Abstraction
This diagram illustrates how AuthenticNexAuth uses the PlatformHandle to interact with different server platforms.
Platform Implementations
PaperPlatformHandle: Implements the handle for Paper/Spigot servers. It uses the Bukkit API to manage players and worlds. For example,movePlayeris implemented usingplayer.teleportAsync().VelocityPlatformHandle: Implements the handle for Velocity proxies. It uses the Velocity API to manage players and servers.movePlayeris implemented by creating aConnectionRequest.
Sources: PaperPlatformHandle.java:36, VelocityPlatformHandle.java:41
Plugin Initialization and Lifecycle
The plugin follows a structured initialization sequence when it is enabled. This process ensures that all necessary components are loaded and configured before the plugin begins handling player authentications.
The sequence diagram below shows the key steps in the enable() method of AuthenticNexAuth.
Sources: AuthenticNexAuth.java:218-285
Database and Data Model
NexAuth uses a flexible database layer to store user data, supporting multiple database systems like SQLite, MySQL, and PostgreSQL.
Database Abstraction
The system uses several interfaces to abstract database operations:
DatabaseConnector: Manages the low-level connection to a specific database (e.g.,AuthenticMySQLDatabaseConnector).ReadDatabaseProvider/WriteDatabaseProvider: Define contracts for reading and writing user data, separating data access logic from the connection itself.ReadDatabaseProviderRegistration: A registration object used to register new database providers and their associated connectors.
This design allows new database types or migration sources to be added easily by implementing these interfaces and registering them during startup.
Sources: AuthenticNexAuth.java:100-103, 477-594, NexAuthPlugin.java:111-125
User Data Model
The primary data entity is User, implemented by the AuthenticUser class. It stores all information related to a player's authentication status and profile.
The following diagram shows the structure of the User entity.
Sources: AuthenticUser.java
Below is a table detailing the fields in the AuthenticUser class.
| Field | Type | Description |
|---|---|---|
uuid | UUID | The unique identifier for the user record. |
premiumUUID | UUID | The Mojang UUID if the player is a premium user. Null otherwise. |
hashedPassword | HashedPassword | The user's hashed password. Null if not registered. |
lastNickname | String | The last username the player used. |
joinDate | Timestamp | The date and time the user first joined. |
lastSeen | Timestamp | The date and time the user was last seen. |
secret | String | The secret key for TOTP 2FA. |
ip | String | The last known IP address of the user. |
lastAuthentication | Timestamp | The timestamp of the last successful authentication. |
lastServer | String | The name of the last server the player was on. |
email | String | The user's email address for recovery purposes. |
Sources: AuthenticUser.java:15-30
Configuration System
Configuration is handled by the Configurate library, wrapped in helper classes ConfigurateConfiguration and ConfigurateHelper. All configuration keys are statically defined in the ConfigurationKeys class.
ConfigurateConfiguration: Manages the loading, saving, and migration of a configuration file (e.g.,config.yml).ConfigurateHelper: Provides convenient methods to get and set values from the configuration nodes.ConfigurationKeys: A central repository for allConfigurationKeyobjects. Each key defines its path, default value, comment, and a function to retrieve its value. This provides a type-safe and well-documented way to access configuration values.
Sources: ConfigurateConfiguration.java, ConfigurateHelper.java, ConfigurationKeys.java
Example Configuration Keys
| Key Path | Default Value | Description |
|---|---|---|
limbo | ["limbo0", "limbo1"] | The authentication servers/worlds players are sent to when not authenticated. |
lobby | {"root": ["lobby0", "lobby1"]} | The servers/worlds players are sent to after successful authentication. |
default-crypto-provider | "BCrypt-2A" | The default algorithm for hashing new passwords. |
database.type | "nexauth-sqlite" | The type of database to use for storing user data. |
totp.enabled | true | Enables or disables Time-based One-Time Password (TOTP) 2FA. |
auto-register | false | If true, automatically registers players with a premium username. |
Sources: ConfigurationKeys.java:29, 41, 72, 203, 290, 161
Summary
The system architecture of NexAuth is built on principles of modularity and abstraction. By separating the core business logic in AuthenticNexAuth from platform-specific details in PlatformHandle implementations, the plugin achieves multi-platform support with a maintainable and extensible codebase. The robust configuration system, flexible database layer, and clear API contract further contribute to its design, allowing server administrators to customize its behavior and developers to build upon its functionality.