feat(web): web-initiated YouTube OAuth connect flow (ADR-006)
Add GET /oauth/youtube/connect and /oauth/youtube/callback, mounted inside the login + registration guard so CurrentUserID is always set and every connection binds to the authenticated tapir user. - connect: generate a per-user CSRF state (single-use, short TTL, bound to the user), redirect to Google consent with access_type=offline and prompt=consent so a refresh token comes back. - callback: verify the state belongs to this user, exchange the code via the existing auth.Exchange, persist the refresh token under a PER-USER ref (web.YouTubeTokenRef = "youtube/<userID>/refresh_token") so tenants never collide, then UpsertConnection (provider=youtube, status=active). Any failure renders a clean error page and leaves no half-written state. Reuses auth.Exchange and adds auth.AuthCodeURL (offline + consent) rather than the CLI's listener/terminal flow (ADR-006: web flow, not CLI). The ConnectHandler depends on a narrow web.Connections port, not the concrete store. Wired in cmdServe only when YT client credentials are present; TAPIR_YT_CONNECT_REDIRECT_URL configures the callback URL. Per-user token-ref scheme documented in docs/homelab-integration.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -79,6 +79,14 @@ This maps directly onto the copied `llm` package: `Client` is the OpenAI-compati
|
||||
`SecretStore` port (`youtube.New(cfg, secrets)`). Pinning the actual vault-item name only
|
||||
changes wiring/config, not the adapter — so this `confirm` does not block the adapter. Decide
|
||||
the name when wiring the live connection and record it here.
|
||||
- **Per-user token-ref scheme (Stage 1 web connect):** the web connect flow
|
||||
(`/oauth/youtube/connect` → `/oauth/youtube/callback`) persists each user's refresh token
|
||||
under a **per-user ref `youtube/<userID>/refresh_token`** (`web.YouTubeTokenRef`), not the
|
||||
Stage-0 single `youtube/refresh_token`. This is what keeps tokens isolated across tenants
|
||||
behind the `SecretStore` port; the `video_connections` row stores only this opaque
|
||||
`token_ref`, never the token. The connect callback URL is
|
||||
`TAPIR_YT_CONNECT_REDIRECT_URL` (default `https://tapir.d-ma.be/oauth/youtube/callback`) and
|
||||
must be in the Google OAuth client's authorized redirects for live connect.
|
||||
|
||||
## Hosts (for reference)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user