Table of Contents

Class SrpAuthenticatorCore<TConnection>

Namespace
FishMMO.Auth.Implementation
Assembly
FishMMO-ServerAuth.dll

Engine-independent SRP-6a authenticator core for LoginServer use. Extends BaseAuthenticatorCore<TConnection> with bounded-channel SRP verify/proof workers, TOTP two-factor authentication, kick-request tracking, and per-IP/per-account rate limiting — with no dependency on Unity, FishNet, or any game-engine type.

Subclasses provide transport-specific callbacks for broadcasting auth results, disconnecting connections, resolving IP addresses, and performing database operations.

public abstract class SrpAuthenticatorCore<TConnection> : BaseAuthenticatorCore<TConnection>

Type Parameters

TConnection

The type representing a network connection.

Inheritance
SrpAuthenticatorCore<TConnection>
Inherited Members

Constructors

SrpAuthenticatorCore(ISrpAccountManager<TConnection>)

Initializes the SRP authenticator core.

protected SrpAuthenticatorCore(ISrpAccountManager<TConnection> accountManager)

Parameters

accountManager ISrpAccountManager<TConnection>

SRP account manager instance.

Properties

AccountVerifyDebounceSeconds

Minimum seconds between account-verify debounce entries for the same identifier. Override to 0 in test subclasses to disable per-username rate limiting between sessions.

protected virtual float AccountVerifyDebounceSeconds { get; }

Property Value

float

IsWorkerIdle

Sweeps the kick-request debounce and auth rate-limit trackers. Call from the hosting environment's per-tick update alongside Tick().

public override bool IsWorkerIdle { get; }

Property Value

bool

LoginServerId

LoginServer database ID, embedded in issued tokens.

public long LoginServerId { get; set; }

Property Value

long

MaxConcurrentTotpVerifications

Default maximum number of TOTP code verifications running concurrently. Configurable via .cfg SrpMaxConcurrentTotp.

public int MaxConcurrentTotpVerifications { get; set; }

Property Value

int

MaxLoginFailuresPerUsername

Maximum SRP proof failures tracked per username before that username is locked out. Override to 0 in test subclasses to disable the lockout.

protected virtual int MaxLoginFailuresPerUsername { get; }

Property Value

int

Remarks

Higher than the TOTP threshold on purpose. A TOTP code is six digits read off a screen and typed immediately, so fifteen failures is already generous; a password is typed from memory by someone who may have several, and locking a legitimate owner out of their own account is itself a denial of service. Ten failures inside the window is well beyond ordinary mistyping and far below what guessing needs.

ProofChannelCapacity

Default maximum pending SRP proof requests in the bounded channel. Configurable via .cfg SrpProofChannelCapacity.

public int ProofChannelCapacity { get; set; }

Property Value

int

ProofWorkerCount

Default number of concurrent SRP proof worker tasks. Configurable via .cfg SrpProofWorkers.

public int ProofWorkerCount { get; set; }

Property Value

int

TokenExpirationMinutes

Token validity duration in minutes.

public float TokenExpirationMinutes { get; set; }

Property Value

float

TokenSigningKey

HMAC signing key for token generation. Set by the server system on startup. If null, token issuance is disabled.

public byte[]? TokenSigningKey { get; set; }

Property Value

byte[]

TokenSigningKeyId

Database ID of the HMAC signing key used for token generation.

public long TokenSigningKeyId { get; set; }

Property Value

long

TotpMasterKey

AES-256 master key for decrypting TOTP secrets from the database during login. Must match the key used by AccountCreationSystem.

public byte[]? TotpMasterKey { get; set; }

Property Value

byte[]

VerifyChannelCapacity

Default maximum pending SRP verify requests in the bounded channel. Configurable via .cfg SrpVerifyChannelCapacity.

public int VerifyChannelCapacity { get; set; }

Property Value

int

VerifyWorkerCount

Default number of concurrent SRP verify worker tasks. Configurable via .cfg SrpVerifyWorkers.

public int VerifyWorkerCount { get; set; }

Property Value

int

Methods

BroadcastSrpSuccess(TConnection, byte[], ClientAuthenticationResult, byte[]?)

Broadcasts the SRP success response (encrypted server proof + result + optional token) to the client.

protected abstract void BroadcastSrpSuccess(TConnection conn, byte[] encryptedServerProof, ClientAuthenticationResult result, byte[]? encryptedToken)

Parameters

conn TConnection

Target connection.

encryptedServerProof byte[]

AES-GCM encrypted server proof bytes.

result ClientAuthenticationResult

Auth result code accompanying the proof.

encryptedToken byte[]

AES-GCM encrypted auth token, or null if login was not successful.

BroadcastSrpVerifyResponse(TConnection, byte[], byte[])

Broadcasts a generic auth result to the client.

protected abstract void BroadcastSrpVerifyResponse(TConnection conn, byte[] encryptedSalt, byte[] encryptedPublicServerEphemeral)

Parameters

conn TConnection

Target connection.

encryptedSalt byte[]

AES-GCM encrypted SRP salt.

encryptedPublicServerEphemeral byte[]

AES-GCM encrypted server public ephemeral.

CheckHasPendingKickAsync(string)

Checks whether a pending kick request exists for the given account name.

protected abstract Task<bool> CheckHasPendingKickAsync(string username)

Parameters

username string

Account name to check.

Returns

Task<bool>

true if a pending kick is recorded; otherwise, false.

CheckIsOnlineAsync(string)

Checks whether any character for the given account name is currently online.

protected abstract Task<bool> CheckIsOnlineAsync(string username)

Parameters

username string

Account name to check.

Returns

Task<bool>

true if any session for this account is active; otherwise, false.

FetchAccountForLoginAsync(string, bool)

Fetches account data for SRP login (by username or email).

protected abstract Task<SrpAuthenticatorCore<TConnection>.SrpAccountLookupResult> FetchAccountForLoginAsync(string identifier, bool isEmail)

Parameters

identifier string

Username or email address.

isEmail bool

True if identifier is an email address.

Returns

Task<SrpAuthenticatorCore<TConnection>.SrpAccountLookupResult>

An SrpAuthenticatorCore<TConnection>.SrpAccountLookupResult with account data if found.

InitializeWorkersCore(CancellationToken)

Subclass-specific worker initialization: create channels and start worker tasks. Called after the base generates the cookie key.

protected override void InitializeWorkersCore(CancellationToken cancellationToken)

Parameters

cancellationToken CancellationToken

Token for signalling worker shutdown.

IsAllowedEmailUsername(string)

Validates an email-format username against the allowed email username rules. Delegates to Authentication.IsAllowedEmailUsername (FishMMO-SharedUtility).

protected abstract bool IsAllowedEmailUsername(string username)

Parameters

username string

The email address to validate.

Returns

bool

true if the email is a valid login identifier; otherwise, false.

IsAllowedUsername(string)

Validates a username against the allowed username rules. Delegates to Authentication.IsAllowedUsername (FishMMO-SharedUtility).

protected abstract bool IsAllowedUsername(string username)

Parameters

username string

The username string to validate.

Returns

bool

true if the username is allowed; otherwise, false.

IsConnectionActive(TConnection)

Returns whether a connection is currently active (connected and not disposed).

protected abstract bool IsConnectionActive(TConnection conn)

Parameters

conn TConnection

The connection to check.

Returns

bool

true if the connection is still active; otherwise, false.

OnAuthSweep()

Override for subclass-specific logic that runs alongside the stale-auth sweep.

protected override void OnAuthSweep()

OnAuthenticationResult(TConnection, bool)

Called when an authentication result (success or failure) must be reported for a connection. Implementations should call OnAuthenticationResult event, FishNet's PassAuthentication/FailAuthentication, etc.

protected abstract void OnAuthenticationResult(TConnection conn, bool authenticated)

Parameters

conn TConnection

The authenticated (or rejected) connection.

authenticated bool

True if authentication succeeded.

OnPurgeConnectionState(TConnection)

Override for subclass-specific cleanup during connection purge. Called before AccountManager.RemoveConnectionAccount but after ClearTransientAuthState(int) has removed TTL tracking.

protected override void OnPurgeConnectionState(TConnection conn)

Parameters

conn TConnection

The connection being purged.

OnSrpProofReceived(TConnection, byte[], uint)

Gate for an incoming SRP proof request. Validates connection state and enqueues for async processing. No decryption or SRP math occurs here.

public void OnSrpProofReceived(TConnection conn, byte[] encryptedProof, uint seq)

Parameters

conn TConnection

The network connection.

encryptedProof byte[]

Encrypted proof bytes.

seq uint

Broadcast sequence number.

OnSrpVerifyReceived(TConnection, byte[], byte[], uint)

Gate for an incoming SRP verify request. Validates connection state, applies rate limits, and enqueues for async processing. No decryption or database work occurs here.

public void OnSrpVerifyReceived(TConnection conn, byte[] encryptedUsername, byte[] encryptedPublicEphemeral, uint seq)

Parameters

conn TConnection

The network connection.

encryptedUsername byte[]

Encrypted username bytes.

encryptedPublicEphemeral byte[]

Encrypted public ephemeral bytes.

seq uint

Broadcast sequence number.

OnTwoFactorVerifyReceived(TConnection, byte[], uint)

Gate for an incoming TOTP verification code. Validates state, applies rate limits, and dispatches async processing.

public void OnTwoFactorVerifyReceived(TConnection conn, byte[] encryptedCode, uint seq)

Parameters

conn TConnection

The network connection.

encryptedCode byte[]

Encrypted TOTP code bytes.

seq uint

Broadcast sequence number.

PersistKickRequestAsync(string)

Persists a kick request for the given account name to the database.

protected abstract Task PersistKickRequestAsync(string username)

Parameters

username string

Account name to kick.

Returns

Task

PersistTokenHashAsync(string, string, int)

Persists the hashed token for the given account to the database (for revocation tracking).

protected abstract Task PersistTokenHashAsync(string username, string tokenHash, int expirationMinutes)

Parameters

username string

Account name.

tokenHash string

SHA-256 hex hash of the raw token.

expirationMinutes int

Token validity duration.

Returns

Task

ResolveClientRealIp(TConnection)

Attempts to complete login and returns the final auth result. Override to apply server-type-specific login logic (e.g., WorldServer player limit checks). Default: returns defaultResult unchanged.

protected virtual string? ResolveClientRealIp(TConnection conn)

Parameters

conn TConnection

Returns

string

The final ClientAuthenticationResult to send to the client.

ShutdownWorkersCore()

Subclass-specific worker shutdown: complete channel writers, null channel references, and clear subclass-specific state. Called BEFORE the base zeroes the cookie key.

protected override void ShutdownWorkersCore()

TickRateLimits()

Sweeps the kick-request debounce and auth rate-limit trackers. Call from the hosting environment's per-tick update alongside Tick().

public void TickRateLimits()

TryLoginAsync(ClientAuthenticationResult, string)

Attempts to complete login authentication. Override in subclasses for server-type-specific logic (e.g., WorldServer checks player limit).

protected virtual Task<ClientAuthenticationResult> TryLoginAsync(ClientAuthenticationResult defaultResult, string username)

Parameters

defaultResult ClientAuthenticationResult
username string

Returns

Task<ClientAuthenticationResult>

TryResendVerificationEmailIfExpiredAsync(string, DateTime?)

Called when an unverified account attempts login. The implementation should check whether the verification code has expired and, if so, generate a new code and enqueue a fresh verification email. No-op when the code is still valid or when the email has not yet been sent (VerificationEmailSentAt is null).

protected abstract Task<bool> TryResendVerificationEmailIfExpiredAsync(string username, DateTime? verifyCodeExpiresUtc)

Parameters

username string

The account username.

verifyCodeExpiresUtc DateTime?

UTC expiry of the current code, or null.

Returns

Task<bool>

True if a new code was generated and the email was enqueued.

VerifyTotpCodeAsync(string, string, byte[])

Verifies a TOTP code for the given username against the database-stored secret.

protected abstract Task<bool> VerifyTotpCodeAsync(string username, string totpCode, byte[] totpMasterKey)

Parameters

username string

Account name.

totpCode string

6-digit TOTP code (plaintext).

totpMasterKey byte[]

AES-256 key for decrypting the stored TOTP secret.

Returns

Task<bool>

True if the code is valid; false otherwise.