aws-sso: read the session end from AWS's token cap; log in 30 s after it
Overnight 2026-10-12: in the session's last hour AWS issued tokens capped at the end (00:18:48 local, 8 h after sign-in); the old 'expiresAt advanced' rule read their millisecond jitter as 'refreshed'. A refusal at 00:13 led to a login that inherited the ending session, and the 30-min wait then delayed the useful login to 00:47. Now: new full token = refreshed; new token issued for < 55 min = capped, its expiry is the end (session_end_seen, status 'until HH:MM'), login at end+30 s; nothing written = refused, login at once. anchor logs token_min/inherited from the cap, not a clock. 2 min between unprompted logins after a success; 30 min, 1 h, 2 h, 4 h after unanswered ones.
This commit is contained in:
@@ -394,23 +394,28 @@ Status and logs show only the ntfy server and a fingerprint of the topic.
|
||||
**How it detects the end.** Per AWS ("Understanding authentication sessions"), the
|
||||
CLI's 1-hour token is refreshed "as long as the underlying user interactive session
|
||||
remains valid", meaning the browser's AWS sign-in. That sign-in is admin-capped and
|
||||
its length is not predictable (measured 8 h on 2026-10-10, at most 6 h on 2026-10-11).
|
||||
When it ends, the next refresh is refused. Inside the SDK's 5-minute pre-expiry
|
||||
window, a refused refresh is *silent*: the SDK keeps returning the still-valid token.
|
||||
So the keeper makes that refresh attempt itself as soon as the window opens: it uses
|
||||
pi's own `@aws-sdk/token-providers` and the same cache file. It then checks whether
|
||||
`expiresAt` in `~/.aws/sso/cache/<sha1(sso-session)>.json` advanced. If it did not,
|
||||
the session is over, and the keeper logs in right away while the old token still
|
||||
covers requests. Nothing is renewed on a clock: a login while the browser sign-in
|
||||
is still valid completes silently ("…can be used until your session expires") but
|
||||
inherits its end, so it gains nothing. Tokens are only ever logged as `sha256[:8]`
|
||||
measured 8 h here (2026-10-10 from the portal cookie; 2026-10-12 from the token cap
|
||||
below). In the session's last hour AWS still issues new 1-hour tokens but **caps them
|
||||
at the session's end**; after the end it refuses. Inside the SDK's 5-minute pre-expiry
|
||||
window both are *silent*: the SDK keeps returning a still-valid token. So the keeper
|
||||
makes that refresh attempt itself as soon as the window opens, with pi's own
|
||||
`@aws-sdk/token-providers` and the same cache file
|
||||
(`~/.aws/sso/cache/<sha1(sso-session)>.json`), and reads the result from the file:
|
||||
a new full token = alive; a new token issued for under 55 min = **capped**, and its
|
||||
expiry is the session's end; nothing written = **refused**. On a cap the keeper logs
|
||||
in 30 s after that end. On a refusal it logs in at once while the old token still
|
||||
covers requests. Refusals also happened with time left (cause unknown): a probe at
|
||||
00:13 local on 2026-10-12, 5 min before the end, and a failed request ~2 h before it;
|
||||
both times a login worked at once. Nothing is renewed on a clock, and never
|
||||
before a known end: a login while the browser sign-in is valid completes silently
|
||||
("…can be used until your session expires") but inherits its end, so it gains nothing. Tokens are only ever logged as `sha256[:8]`
|
||||
fingerprints (`~/.pi/agent/aws-sso/events.jsonl`); the token the SDK returns is
|
||||
dropped unread.
|
||||
|
||||
**Triggers:** a 20 s timer that checks every 60 s inside the refresh window (every
|
||||
10 min once the token has run out). Unprompted logins back off (retries after 30 min,
|
||||
1 h, 2 h, then every 4 h), so one waiting for you does not pile up tabs or
|
||||
pushes overnight. `before_agent_start`
|
||||
10 min once the token has run out). At least 2 min pass between unprompted logins;
|
||||
after an unanswered one the keeper retries after 30 min, 1 h, 2 h, then every 4 h, so
|
||||
a login waiting for you does not pile up tabs or pushes overnight. `before_agent_start`
|
||||
checks first if the token is in its window and logs in (and waits) if the session
|
||||
is over. `message_end` is the fallback: if a request still fails on an expired
|
||||
token, the keeper renews and sends `continue` (once per 10 min), also when you
|
||||
|
||||
Reference in New Issue
Block a user