Skip to content

Fix intermittent GetAuthSessionTicket hang / "Ticket verification failed" on repeated calls (#1567) - #1645

Merged
xPaw merged 1 commit into
SteamRE:masterfrom
molecul:fix/authticket-crc-correlation-1567
Sep 12, 2026
Merged

xPaw merged 1 commit into
SteamRE:masterfrom
molecul:fix/authticket-crc-correlation-1567

Conversation

@molecul

@molecul molecul commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Fixes #1567.

Problem

GetAuthSessionTicket / GetAuthTicketForWebApi work on the first call but intermittently break on
subsequent calls in the same session. This regressed after a Steam-side change (reported around Steam's
2025-08 downtime) and shows up two ways:

  • Same appid, repeated call: the returned task hangs until the caller times out.
  • A different appid: throws Ticket verification failed, even though the ticket was submitted and is valid.

Both stem from how the auth-list acknowledgement is correlated. SendTickets() sends CMsgClientAuthList
with a fresh SourceJobID and returns an AsyncJob<TicketAcceptedCallback> keyed on it;
HandleTicketAcknowledged posts the callback keyed on TargetJobID. Steam's ack for a repeated auth list is
now unreliable:

  • it may not carry a matching TargetJobID (no re-ack), so the AsyncJob never completes, which hangs; and
  • its ticket_crc list may not include the just-added ticket's CRC (it echoes an already-active one instead),
    so the ActiveTicketsCRC.Any(...) check in GetAuthSessionTicketInternal misses and throws.

Root-cause diagnosis credit: @K4ryuu in #1567.

Fix

Correlate the acknowledgement by ticket CRC instead of JobID, and stop treating a missing ack as fatal:

  • Register a per-CRC TaskCompletionSource before sending the auth list.
  • Complete it in HandleTicketAcknowledged by matching CMsgClientAuthListAck.ticket_crc.
  • Await it with a timeout. On timeout, log via DebugLog and return the ticket anyway instead of throwing:
    the ticket has already been submitted and is validated server-side via BeginAuthSession, so a missing
    client-side ack is no longer a reliable failure signal.

TicketAcceptedCallback is still posted, so existing consumers are unaffected. SendTickets() no longer
needs to return an AsyncJob.

Testing

Validated against live Steam on .NET 10, same account, patched build vs stock 3.4.0:

  • Stock: requesting a ticket for a second, different appid (after one was already active) returned
    Ticket verification failed - the reported throw, reproduced live.
  • Patched: the same sequence returned a valid 234-byte ticket.
  • Repeated same-appid calls returned successfully on both builds in our environment (the hang mode is
    intermittent and Steam-state dependent; it is reported by multiple users but did not reproduce on demand
    here). The CRC-correlation + timeout path handles it by construction: a non-acked call can no longer block
    indefinitely.

Net: ticket retrieval is now robust to Steam's unreliable acks - it neither hangs nor throws spuriously,
whether or not Steam echoes the new ticket's CRC.

…t calls

Steam's acknowledgement for a repeated ClientAuthList is now unreliable: it
may omit a matching TargetJobID (so the AsyncJob never completes and the call
hangs) or omit the new ticket's CRC from ticket_crc (so the ActiveTicketsCRC
check misses and throws "Ticket verification failed"), even though the ticket
is valid and is validated server-side via BeginAuthSession.

Register a per-CRC TaskCompletionSource before sending, complete it in
HandleTicketAcknowledged by matching CMsgClientAuthListAck.ticket_crc, and await
it with a timeout; on timeout log and return the ticket instead of throwing.
TicketAcceptedCallback is still posted, so existing consumers are unaffected.

Fixes SteamRE#1567.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: GetAuthSessionTicket stops working after the 2nd call

2 participants