fbf8ca38b0
Replace client-controlled redirectUri with server-side redirect intents. The portal server component validates the ?rd= hostname against isForwardAuthDomain, stores the URI in a new forward_auth_redirect_intents table, and passes only an opaque rid (128-bit random, SHA-256 hashed) to the client. Login endpoints consume the intent atomically (one-time use, 10-minute TTL) and retrieve the stored URI — the client never sends the redirect URL to any API endpoint. Security properties: - Redirect URI is never client-controlled in API requests - rid is 128-bit random, stored as SHA-256 hash (not reversible from DB) - Atomic one-time consumption prevents replay - 10-minute TTL limits attack window for OAuth round-trip - Immediate deletion after consumption - Expired intents cleaned up opportunistically - Hostname validated against registered forward-auth domains before storage Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>