- Shipped
- October 18, 2026 at 6:52 AM UTC
- Author
- Kamo
- Commit
- 9916478
/api/login, /api/session/select and /api/login/mfa accept an optional oauthRequestId (64 hex). Absent, nothing changes (tests/***-cookie pins each route's answer and Set-Cookie). Present but malformed: 400 before anything is asked of SecurityService. Valid, once SecurityService answered with a one-time key and the *** id was read from OTK<otk> as today: O3 attach spends the key, the browser gets {success, oauthNext} and never the key or the workspace redirect, and the *** cookie is planted exactly as an ordinary sign-in plants it — only when consent is next (an expired request or a fault leaves no cookie). An unspendable key is told as a fault, never as a credential error. MFA and workspace answers are relayed as today; the page keeps the request id and sends it with the next call. OAuthSignIn (own markup in OAuthShell): username/password with the same proof-of-work capcha, StrikeMeter/LockoutPanel unchanged, MfaStep (new: six-digit code or recovery code, its own lockout), WorkspacePicker unchanged with logos left out (they live on theme.<apex>). MfaStep is used only here; the standard page is not touched. /oauth/consent: client and scopes, the iot.voice explanation (spec 4.24.3), NEW link (name 1-120, default Alexa) or REPLACE per listed link, eligibility reasons in words (SI, not AI), Link Alexa / Cancel; follows redirectTo only when it is https: (O4 lists no redirect URIs to compare with). **************** relay O2/O4/O5 with the *** cookie as X-***-Token, forward only consentToken/decision/link, and clear the cookie when a decision is done. handoff is handoff.mjs (not .ts) so node --test can import it.
