Xirsys.XTurn.Auth.NonceStore (xturn v2.0.0)

Copy Markdown View Source

Tracks STUN/TURN nonces per client endpoint before an allocation exists.

What problem this solves

Long-term authentication (RFC 8489/5389) requires the server to issue a fresh NONCE on 401 Unauthorized and verify MESSAGE-INTEGRITY on retry. Clients must not replay stale nonces. This GenServer stores one nonce per client {ip, port} (and supports IP-wide lookup for TCP ConnectionBind on a new five-tuple), expiring entries after :nonce_max_age_ms.

Internal: hot-path authentication calls issue/1, validate/2, and validate_for_ip/2; operators configure expiry via application env only.

RFCs

  • RFC 8489 (MESSAGE-INTEGRITY, NONCE, PASSWORD-ALGORITHMS)
  • RFC 5389 (STUN long-term credential mechanism)
  • RFC 8656 (TURN stale nonce, 438 Stale Nonce, pt.7.2)

Summary

Functions

Returns a specification to start this module under a supervisor.

Returns the current nonce for client_key, or nil when none was issued.

Issues a fresh nonce for client_key {ip, port} and stores it.

Returns the PASSWORD-ALGORITHMS attribute value for RFC 8489 support.

Starts the nonce store (registered as __MODULE__).

Validates nonce against the value stored for client_key.

Validates nonce against any live nonce issued to ip.

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

current(client_key)

@spec current({:inet.ip_address(), pos_integer()}) :: String.t() | nil

Returns the current nonce for client_key, or nil when none was issued.

issue(client_key)

@spec issue({:inet.ip_address(), pos_integer()}) :: String.t()

Issues a fresh nonce for client_key {ip, port} and stores it.

Replaces any previous nonce for the same key.

password_algorithms()

@spec password_algorithms() :: binary()

Returns the PASSWORD-ALGORITHMS attribute value for RFC 8489 support.

Advertises MD5 (1) and SHA-256 (2) with zero-length parameters.

start_link(opts \\ [])

Starts the nonce store (registered as __MODULE__).

validate(client_key, nonce)

@spec validate(
  {:inet.ip_address(), pos_integer()},
  String.t() | nil
) :: :ok | :missing | :mismatch | :stale

Validates nonce against the value stored for client_key.

Returns :ok, :missing, :mismatch, or :stale.

validate_for_ip(ip, nonce)

@spec validate_for_ip(:inet.ip_address(), String.t() | nil) :: :ok | :missing | :stale

Validates nonce against any live nonce issued to ip.

Used when ConnectionBind arrives on a new TCP five-tuple but reuses the nonce issued to the client IP during the initial Allocate exchange.