auth: link Steam to UDID-keyed viewer on first authenticated request
After /tool/signup, the client has a viewer_id but no Steam social row. The first authenticated request (typically /check/game_start) carries the Steam ticket; if the SteamId lookup misses but the UDID resolves to a viewer, attach the Steam social now. Subsequent requests hit the fast SteamId path. Closes the CheckController.GameStart TODO that was blocking fresh-client boot. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -30,10 +30,6 @@ public class CheckController : SVSimController
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: spec lists this as anonymous (identity from SHORT_UDID), but the base controller's
|
||||
// [Authorize] still applies. For now requires a Steam-linked viewer; new-user bootstrap (where
|
||||
// the server creates a viewer + returns rewrite_viewer_id) is deferred until the boot flow is
|
||||
// exercised end-to-end with a real client.
|
||||
[HttpPost("game_start")]
|
||||
public async Task<GameStartResponse> GameStart(GameStartRequest request)
|
||||
{
|
||||
|
||||
@@ -97,13 +97,33 @@ public class SteamSessionAuthenticationHandler : AuthenticationHandler<SteamAuth
|
||||
|
||||
if (viewer is null)
|
||||
{
|
||||
// Most common dev-loop cause: DB was re-bootstrapped and this Steam account hasn't
|
||||
// been re-linked yet. Log loudly with the steam_id so it's obvious what to add back.
|
||||
Logger.LogWarning(
|
||||
"Auth: no viewer linked to steamId={SteamId} on {Path}. " +
|
||||
"Likely you re-bootstrapped the DB without re-linking this Steam account.",
|
||||
requestJson.SteamId, path);
|
||||
return AuthenticateResult.Fail("User not found.");
|
||||
// Find-or-link: first authenticated request after /tool/signup. The client signed up
|
||||
// anonymously and has no Steam social row yet; if the UDID resolves to a viewer, attach
|
||||
// Steam to it now so subsequent requests hit the fast SteamId path. The SteamId unique
|
||||
// index on SocialAccountConnection is the dedup backstop for concurrent first-touch.
|
||||
Guid? udid = Context.GetUdid();
|
||||
if (udid is Guid u && u != Guid.Empty)
|
||||
{
|
||||
viewer = await _viewerRepository.GetViewerByUdid(u);
|
||||
if (viewer is not null)
|
||||
{
|
||||
await _viewerRepository.LinkSteamToViewer(viewer.Id, requestJson.SteamId);
|
||||
// Re-read with socials so transition_account_data downstream sees the new link.
|
||||
viewer = await _viewerRepository.GetViewerWithSocials(viewer.Id) ?? viewer;
|
||||
Logger.LogInformation(
|
||||
"Auth: linked steamId={SteamId} to UDID-keyed viewer_id={ViewerId} on {Path} (first-Steam-touch).",
|
||||
requestJson.SteamId, viewer.Id, path);
|
||||
}
|
||||
}
|
||||
|
||||
if (viewer is null)
|
||||
{
|
||||
Logger.LogWarning(
|
||||
"Auth: no viewer linked to steamId={SteamId} on {Path}, and no UDID-keyed viewer to link to. " +
|
||||
"Client must call /tool/signup before authenticated endpoints.",
|
||||
requestJson.SteamId, path);
|
||||
return AuthenticateResult.Fail("User not found.");
|
||||
}
|
||||
}
|
||||
|
||||
// Add viewer to context
|
||||
|
||||
Reference in New Issue
Block a user