UDP Auth Flow Example¶
This guide explains the actual UDP authentication shape used by UdpListenerBase today, in a client-friendly way.
What the runtime expects¶
When UdpListenerBase receives a datagram, it expects the payload to end with authentication metadata:
- connection/session identifier
- timestamp
- authentication tag
In source, the listener validates:
- session exists in
ConnectionHub - replay window is still valid
- Poly1305 tag matches payload + metadata + remote endpoint
- your overridden
IsAuthenticated(...)also returnstrue
High-level flow¶
flowchart LR
A["UDP datagram received"] --> B["Extract session id + timestamp + auth tag"]
B --> C["Find connection in ConnectionHub"]
C --> D["Validate replay window"]
D --> E["Validate Poly1305 tag"]
E --> F["Call IsAuthenticated(...)"]
F --> G["Inject payload into connection"]
Server shape¶
1. Subclass UdpListenerBase¶
public sealed class SampleUdpListener : UdpListenerBase
{
public SampleUdpListener(IProtocol protocol) : base(protocol) { }
protected override bool IsAuthenticated(IConnection connection, in UdpReceiveResult result)
{
// Add your own checks here:
// - allowed endpoint
// - session state
// - region / shard ownership
return connection.Secret is not null && connection.Secret.Length > 0;
}
}
2. Keep TCP and UDP tied to the same session¶
The UDP path assumes there is already a known connection in ConnectionHub.
That means a common pattern is:
- authenticate or handshake on TCP first
- create/populate the connection secret
- store the session in
ConnectionHub - allow UDP packets to reference that session ID
Conceptual client packet layout¶
The listener currently validates these parts:
The authentication tag is computed from:
- payload
- session ID bytes
- timestamp bytes
- encoded remote endpoint
- the connection secret
Pseudocode for client-side send¶
byte[] payload = BuildGamePayload();
byte[] sessionId = connectionId.ToBytes();
long timestamp = CurrentUnixMilliseconds();
byte[] tag = ComputePoly1305(
secret: sessionSecret,
payload: payload,
sessionId: sessionId,
timestamp: timestamp,
remoteEndPoint: serverEndPoint);
byte[] datagram = Concat(payload, sessionId, BitConverter.GetBytes(timestamp), tag);
await udp.SendAsync(datagram, serverEndPoint);
Replay protection¶
The runtime rejects datagrams that fall outside the replay window.
Today the code uses a window of about 30 seconds, so clients should:
- keep clocks reasonably aligned
- generate timestamps at send time
- avoid replaying stale datagrams
What happens on failure¶
The listener records diagnostics for:
- short packets
- unknown sessions
- unauthenticated packets
- receive errors
Invalid packets are dropped before they reach your protocol logic.
Recommended rollout¶
For a simple deployment:
- establish session over TCP
- assign/store session secret
- return session ID to the client
- let the client send authenticated UDP datagrams
- verify in
IsAuthenticated(...)that the session is ready for UDP