mirror of
https://github.com/seanbetts/steam-hardware-watch.git
synced 2026-10-04 22:00:11 +02:00
Improve SteamKit auth bootstrap
This commit is contained in:
1 parent
fc0a08825d
commit
6c47978228
5 files changed
+62
-7
No files matched your search
@@ -144,7 +144,8 @@ mkdir -p .local
|
||||
cat > .local/steamkit-env.sh <<'EOF'
|
||||
STEAMKIT_USERNAME='your-watch-account'
|
||||
STEAMKIT_PASSWORD='your-watch-account-password'
|
||||
# Use one of these only for the one-time session bootstrap when Steam Guard asks for it:
|
||||
# Usually leave these unset and enter the code when scripts/steamkit_auth.sh prompts.
|
||||
# For non-interactive use, set one of these only when Steam Guard asks for it:
|
||||
# STEAMKIT_AUTH_CODE='email-code'
|
||||
# STEAMKIT_TWO_FACTOR_CODE='authenticator-code'
|
||||
# Or approve the mobile prompt manually, then set:
|
||||
|
||||
@@ -148,7 +148,8 @@ Use a narrow SteamKit2 helper when available. It should:
|
||||
SteamKit auth handling:
|
||||
|
||||
- keep `.local/steamkit-env.sh` and `.local/steamkit-session.json` local and uncommitted
|
||||
- use `STEAMKIT_AUTH_CODE`, `STEAMKIT_TWO_FACTOR_CODE`, or `STEAMKIT_ACCEPT_MOBILE_CONFIRMATION=1` only for the bootstrap command
|
||||
- prefer an interactive `scripts/steamkit_auth.sh` run for email or mobile guard challenges, because email codes are tied to the active login attempt
|
||||
- use `STEAMKIT_AUTH_CODE`, `STEAMKIT_TWO_FACTOR_CODE`, or `STEAMKIT_ACCEPT_MOBILE_CONFIRMATION=1` only for non-interactive bootstrap commands
|
||||
- remove one-time guard values from `.local/steamkit-env.sh` after `scripts/steamkit_auth.sh` succeeds
|
||||
- if routine checks fail because the refresh token expired or was revoked, ask the user to re-run `scripts/steamkit_auth.sh` with a fresh Steam Guard approval
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ ENV_FILE="${STEAMKIT_ENV_FILE:-$REPO_DIR/.local/steamkit-env.sh}"
|
||||
SESSION_FILE="${STEAMKIT_SESSION_FILE:-$REPO_DIR/.local/steamkit-session.json}"
|
||||
|
||||
if [ -f "$ENV_FILE" ]; then
|
||||
printf '%s\n' "Loading SteamKit environment from $ENV_FILE" >&2
|
||||
# shellcheck disable=SC1090
|
||||
. "$ENV_FILE"
|
||||
fi
|
||||
@@ -33,6 +34,7 @@ fi
|
||||
|
||||
mkdir -p "$(dirname "$SESSION_FILE")"
|
||||
|
||||
printf '%s\n' "Starting SteamKit auth bootstrap. Waiting for Steam to request any required Guard confirmation..." >&2
|
||||
dotnet run --project "$PROJECT_DIR" -- --auth-session-out "$SESSION_FILE" --session-file "$SESSION_FILE"
|
||||
chmod 600 "$SESSION_FILE"
|
||||
printf '%s\n' "Saved SteamKit session to $SESSION_FILE"
|
||||
@@ -125,6 +125,7 @@ class CheckSteamKitPicsTests(unittest.TestCase):
|
||||
{
|
||||
"PATH": f"{fake_bin}:{env['PATH']}",
|
||||
"STEAMKIT_ENV_FILE": str(tmp_path / "missing-env.sh"),
|
||||
"STEAMKIT_SESSION_FILE": str(tmp_path / "missing-session.json"),
|
||||
}
|
||||
)
|
||||
env.pop("STEAMKIT_USERNAME", None)
|
||||
@@ -483,7 +484,7 @@ class SteamKitAuthScriptTests(unittest.TestCase):
|
||||
check=False,
|
||||
)
|
||||
|
||||
self.assertEqual("", result.stderr)
|
||||
self.assertIn("Starting SteamKit auth bootstrap", result.stderr)
|
||||
self.assertEqual(0, result.returncode)
|
||||
self.assertTrue(session_file.exists())
|
||||
dotnet_args = log_path.read_text(encoding="utf-8")
|
||||
|
||||
@@ -213,9 +213,11 @@ static class AuthClient
|
||||
}
|
||||
});
|
||||
|
||||
Console.Error.WriteLine("Connecting to Steam...");
|
||||
steamClient.Connect();
|
||||
await CallbackPump.UntilAsync(manager, connected.Task, disconnected.Task, cancellationToken);
|
||||
|
||||
Console.Error.WriteLine("Connected. Starting Steam credential auth session...");
|
||||
var authTask = steamClient.Authentication.BeginAuthSessionViaCredentialsAsync(new AuthSessionDetails
|
||||
{
|
||||
Username = username,
|
||||
@@ -230,6 +232,7 @@ static class AuthClient
|
||||
|
||||
await CallbackPump.UntilAsync(manager, authTask, disconnected.Task, cancellationToken);
|
||||
var authSession = await authTask;
|
||||
Console.Error.WriteLine("Auth session created. Waiting for Steam Guard confirmation or token response...");
|
||||
var pollTask = authSession.PollingWaitForResultAsync(cancellationToken);
|
||||
await CallbackPump.UntilAsync(manager, pollTask, disconnected.Task, cancellationToken);
|
||||
var result = await pollTask;
|
||||
@@ -261,7 +264,16 @@ sealed class EnvAuthenticator(string? emailCode, string? deviceCode, bool accept
|
||||
return Task.FromResult(deviceCode);
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Steam mobile authenticator code required. Set STEAMKIT_TWO_FACTOR_CODE and rerun scripts/steamkit_auth.sh.");
|
||||
if (!Console.IsInputRedirected)
|
||||
{
|
||||
return Task.FromResult(ReadRequiredSecret(
|
||||
previousCodeWasIncorrect
|
||||
? "Steam mobile authenticator code was rejected. Enter the current Steam mobile authenticator code: "
|
||||
: "Enter the current Steam mobile authenticator code: "
|
||||
));
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Steam mobile authenticator code required. Set STEAMKIT_TWO_FACTOR_CODE or run scripts/steamkit_auth.sh from an interactive terminal.");
|
||||
}
|
||||
|
||||
public Task<string> GetEmailCodeAsync(string email, bool previousCodeWasIncorrect)
|
||||
@@ -271,10 +283,46 @@ sealed class EnvAuthenticator(string? emailCode, string? deviceCode, bool accept
|
||||
return Task.FromResult(emailCode);
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Steam Guard email code required for {email}. Set STEAMKIT_AUTH_CODE and rerun scripts/steamkit_auth.sh.");
|
||||
if (!Console.IsInputRedirected)
|
||||
{
|
||||
return Task.FromResult(ReadRequiredSecret(
|
||||
previousCodeWasIncorrect
|
||||
? $"Steam Guard email code for {email} was rejected. Enter the latest Steam Guard email code: "
|
||||
: $"Enter the Steam Guard email code sent to {email}: "
|
||||
));
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Steam Guard email code required for {email}. Set STEAMKIT_AUTH_CODE or run scripts/steamkit_auth.sh from an interactive terminal.");
|
||||
}
|
||||
|
||||
public Task<bool> AcceptDeviceConfirmationAsync() => Task.FromResult(acceptMobileConfirmation);
|
||||
public Task<bool> AcceptDeviceConfirmationAsync()
|
||||
{
|
||||
if (acceptMobileConfirmation)
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
if (!Console.IsInputRedirected)
|
||||
{
|
||||
Console.Error.Write("Approve the Steam mobile confirmation, then press Enter to continue.");
|
||||
_ = Console.ReadLine();
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
static string ReadRequiredSecret(string prompt)
|
||||
{
|
||||
Console.Error.Write(prompt);
|
||||
var value = Console.ReadLine();
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
throw new InvalidOperationException("Steam Guard code was empty.");
|
||||
}
|
||||
|
||||
return value.Trim();
|
||||
}
|
||||
}
|
||||
|
||||
static class CallbackPump
|
||||
@@ -292,7 +340,9 @@ static class CallbackPump
|
||||
throw new InvalidOperationException(await disconnected);
|
||||
}
|
||||
|
||||
await manager.RunWaitCallbackAsync(cancellationToken);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
manager.RunWaitCallbacks(TimeSpan.FromMilliseconds(250));
|
||||
await Task.Yield();
|
||||
}
|
||||
|
||||
await primary;
|
||||
|
||||
Reference in new issue
Block a user