feat: verify allocated join authorisations with hmac

This commit is contained in:
Josh Creek
2026-09-01 08:48:48 +01:00
parent 66a1ee8007
commit e25d61d80e
7 changed files with 64 additions and 5 deletions
+25 -1
View File
@@ -56,6 +56,7 @@ var require_join_authorisation := false
var _allowed_join_authorisations: Dictionary = {}
var _active_join_peers: Dictionary = {} # opaque authorisation -> peer_id
var _join_authorisation_context: Dictionary = {}
var _join_signing_key := PackedByteArray()
# Test hook (tests/match_net_smoke.gd): set false before connecting to
# suppress the automatic real hello, so a test can send a deliberately
@@ -92,10 +93,11 @@ func _on_shutting_down() -> void:
_allowed_join_authorisations.clear()
_active_join_peers.clear()
_join_authorisation_context.clear()
_join_signing_key = PackedByteArray()
require_join_authorisation = false
func configure_join_authorisations(tokens: Array, context: Dictionary) -> bool:
func configure_join_authorisations(tokens: Array, context: Dictionary, signing_key: PackedByteArray = PackedByteArray()) -> bool:
var allowed := {}
for token in tokens:
if not token is String or String(token).is_empty():
@@ -105,6 +107,7 @@ func configure_join_authorisations(tokens: Array, context: Dictionary) -> bool:
return false
_allowed_join_authorisations = allowed
_join_authorisation_context = context.duplicate(true)
_join_signing_key = signing_key.duplicate()
require_join_authorisation = true
return true
@@ -233,6 +236,27 @@ func _valid_join_authorisation(token: String) -> bool:
var protocol := str(claims.get("Protocol", ""))
var expires_at := str(claims.get("ExpiresAt", ""))
var expiry := Time.get_unix_time_from_datetime_string(expires_at)
if not _join_signing_key.is_empty():
var signature_token := str(envelope["Signature"])
var signature := Marshalls.base64_to_raw(signature_token)
if signature.size() != 32:
return false
var canonical := PackedByteArray()
var fields := [
str(claims.get("MatchID", "")), str(claims.get("ServerID", "")),
str(claims.get("PlayerID", "")), str(claims.get("SteamID", "")),
str(int(claims.get("Slot", -1))), str(int(claims.get("Team", -1))), protocol,
str(int(claims.get("Generation", 0))), expires_at,
]
for index in fields.size():
canonical.append_array(String(fields[index]).to_utf8_buffer())
if index < fields.size() - 1:
canonical.append(0)
var hmac := HMACContext.new()
hmac.start(HashingContext.HASH_SHA256, _join_signing_key)
hmac.update(canonical)
if hmac.finish() != signature:
return false
return str(claims.get("MatchID", "")) == str(_join_authorisation_context.get("match_id", "")) \
and str(claims.get("ServerID", "")) == str(_join_authorisation_context.get("server_id", "")) \
and protocol == str(_join_authorisation_context.get("protocol", "")) \