fix(multiplayer): expire client sessions proactively

This commit is contained in:
Josh Creek
2026-09-01 22:13:41 +01:00
parent 1e5825b096
commit cfc82bcea5
3 changed files with 40 additions and 0 deletions
+31
View File
@@ -52,6 +52,8 @@ func _ready() -> void:
func _process(_delta: float) -> void:
if not auth_expired and is_session_expired(session_expires_at):
_expire_session()
if _websocket == null:
return
_websocket.poll()
@@ -269,6 +271,21 @@ static func is_valid_access_token(token: String) -> bool:
return separator > 0 and separator < token.length() - 1 and token.length() <= 4096 and not token.contains("\r") and not token.contains("\n")
static func is_session_expired(expires_at: String, now_unix: int = -1) -> bool:
if expires_at.is_empty():
return false
var timestamp_pattern := RegEx.create_from_string("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$")
if timestamp_pattern.search(expires_at) == null:
return true
var expiry_unix := Time.get_unix_time_from_datetime_string(expires_at)
if expiry_unix < 0:
return true
var current_unix := now_unix
if current_unix < 0:
current_unix = int(Time.get_unix_time_from_system())
return expiry_unix <= current_unix
static func is_retryable_mutation_response(response_code: int) -> bool:
return response_code == 0 or response_code == HTTPClient.RESPONSE_REQUEST_TIMEOUT or response_code == HTTPClient.RESPONSE_TOO_MANY_REQUESTS or response_code >= 500
@@ -287,6 +304,9 @@ func _start_request(operation: String, method: HTTPClient.Method, path: String,
return ERR_BUSY if not _operation.is_empty() else ERR_UNAUTHORIZED
if operation != "steam_session" and access_token.is_empty():
return ERR_UNAUTHORIZED
if operation != "steam_session" and is_session_expired(session_expires_at):
_expire_session()
return ERR_UNAUTHORIZED
var headers := PackedStringArray(["Accept: application/json"])
if operation != "steam_session":
headers.append("Authorization: Bearer " + access_token)
@@ -306,6 +326,17 @@ func _start_request(operation: String, method: HTTPClient.Method, path: String,
return OK
func _expire_session() -> void:
if auth_expired:
return
access_token = ""
auth_expired = true
disconnect_event_stream()
state.fail("Session expired; sign in again")
ranked_profile.set_error("Session expired; sign in again")
session_expired.emit()
func _on_request_completed(result: HTTPRequest.Result, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void:
var operation := _operation
_operation = ""