NEXUS_SIGNING_KEY. As of v1.6.1, the validation logic is structured as a composable MessageValidationChain that is shared globally for inbound messages and also available per-addon for custom rules.
How It Works: MessageValidationChain
Inbound validation is handled byMessageValidationChain, a pipeline of MessageValidator instances. Each validator receives the parsed NexusJsonDataContainer and returns a ValidationResult indicating success or a rejection reason. Processing stops immediately if any validator rejects the message.
NexusReceiver builds a global chain applied to every inbound packet:
DataAddon can also define an additional per-addon chain via additionalValidators(). This chain runs after the global chain passes, before any request handler executes.
MessageValidator Interface
ValidationResult is a record with two fields: valid (boolean) and reason (String). Use the static factories:
Global Validation: Three Stages
Every inbound packet passes through these three validators in order. A failure at any stage silently drops the packet and logs a warning. No response is sent.Stage 1: HMAC-SHA256 Signature (SignatureValidator)
Every packet includes a sig field: a Base64-encoded HMAC-SHA256 signature over all other fields in the packet (excluding sig itself), computed using the shared NEXUS_SIGNING_KEY.
When a packet arrives, SignatureValidator:
- Reads all fields except
sig. - Recomputes HMAC-SHA256 using
HmacSigner.sign(payloadWithoutSig, NEXUS_SIGNING_KEY). - Compares the result against the received
sig. - Rejects the packet if they do not match.
Stage 2: Timestamp (TimestampValidator)
Every packet must include a timestamp field (Unix milliseconds). TimestampValidator calculates |now - timestamp|. If the difference exceeds 5 minutes (TIMESTAMP_WINDOW_MILLIS), the packet is rejected.
Stage 3: Nonce Replay Protection (NonceValidator)
Every packet must include a unique nonce string. NonceValidator records each nonce in a ConcurrentHashMap keyed by nonce value with the packet timestamp. A second packet with the same nonce is rejected immediately as a replay attempt.
Expired nonce entries are purged automatically every TIMESTAMP_WINDOW_MILLIS by a background daemon thread, keeping memory usage bounded.
Validation Order
Per-Addon Validation (New in v1.6.1)
OverrideadditionalValidators() in your DataAddon to enforce rules specific to your addon’s data. The returned validators are assembled into an immutable MessageValidationChain once (lazily, thread-safely) and reused for every request that addon receives.
Outbound Signing
Starting from v1.5.1, theMessageAuth system signs every outgoing message from Nexus Core, adding timestamp, nonce, and sig fields to all responses. This applies to:
- All
DataAddonpublish operations (query responses, broadcasts) RedisDataContainerheartbeat messages
sig on incoming responses using the same NEXUS_SIGNING_KEY. Clients that do not yet verify outbound signatures continue to work — backward compatibility is maintained.
Configuring the Signing Key
Set the environment variable before launching Nexus Core and on every Spigot server in the network:If
NEXUS_SIGNING_KEY is not defined, both inbound verification and outbound signing are disabled. A one-time warning is logged. This is acceptable only for local development.Security Coverage Summary
Related Topics
- Configuration — how to set
NEXUS_SIGNING_KEYand the production checklist - Packet Structure —
sig,timestamp, andnoncefield formats for both directions - Data Addon API —
additionalValidators(),registerHandler(), and the fullDataAddonmethod reference - Request Lifecycle — where the security chain fits in the full request flow