whisper-money/config
Víctor Falcón 2041181dc2
fix(mcp): serve OAuth authorize on a dedicated host so the PWA can't capture it (#709)
## Problem

Connecting the MCP connector from **ChatGPT on Android** fails. The
installed Whisper Money PWA is a Chrome **WebAPK** that auto-verifies as
an Android **App Link handler** for the whole app origin (manifest
`scope: "/"`), so `https://whisper.money/oauth/authorize` gets routed
**into the app**. Once inside the standalone app, the redirect back to
the OAuth client can't complete → the connection fails. (Claude works
because it opens OAuth in a Custom Tab.)

Confirmed on an Android emulator: the WebAPK shows `AutoVerify=true`,
`whisper.money: verified`. DB evidence: ChatGPT registers + reaches
consent (auth codes issued) but never exchanges a token.

## Why not `handle_links`

`handle_links: "not-preferred"` (tried in #707, reverted in #708) is
**origin-wide** — it would push *every* `whisper.money` link (bank-auth
callback, email verification, shared deep links) to the browser, not
just `/oauth`. We want links to keep opening the installed app.

## Fix (surgical)

Move the OAuth **authorization server** to a dedicated host outside the
PWA scope. `config('mcp.authorization_server')` becomes env-driven
(`MCP_AUTHORIZATION_SERVER`); in prod → `https://oauth.whisper.money`
(DNS already points at the same app).

Every endpoint derives from the request host (no forced root URL), so
pointing the auth server at the subdomain makes `issuer` +
`authorize`/`token`/`register` all resolve to `oauth.whisper.money` —
**same origin as each other**, no cross-origin metadata mismatch. The
protected resource (`/mcp/oauth`) and **all other app links stay on
`whisper.money`**, so deep-linking into the app is fully preserved. Only
the OAuth flow leaves the app — into the browser, where the round-trip
completes.

## Activation (after merge + deploy)

1. Set `MCP_AUTHORIZATION_SERVER=https://oauth.whisper.money` in prod
env, redeploy.
2. I'll curl the discovery chain to confirm it resolves to the
subdomain.
3. Test the ChatGPT connect on a real phone.

Safe until step 1: env unset → `authorization_server` stays `null` →
current behavior. No effect on local/dev.

## Tests

Added a Pest test: with `mcp.authorization_server` configured,
protected-resource metadata advertises the dedicated host and
auth-server metadata (fetched from that host) keeps `issuer` + all
endpoints on it. App has no `TrustHosts` restriction (already serves the
subdomain) and `SESSION_DOMAIN=null` (host-only cookies — subdomain gets
its own session, no security downgrade).
2026-07-21 13:51:03 +02:00
..
ai_categorization.php fix(ai): handle transient AI provider overloads — stop the Sentry noise and retry the dropped work (#595) 2026-06-26 20:07:06 +02:00
ai_suggestions.php feat(ai): add weekly AI-suggestions cohort report (#530) 2026-06-13 23:23:34 +02:00
app.php feat(demo): gate demo account access behind a config flag (#580) 2026-06-22 11:01:27 +00:00
auth.php feat(mcp): add OAuth 2.1 for Claude Desktop & ChatGPT connectors (Phase 3) (#691) 2026-07-17 19:10:48 +02:00
cache.php chore: upgrade Laravel 12 to 13 (#242) 2026-03-25 12:56:33 +00:00
cashier.php feat(pricing): dynamic Stripe pricing with locale-aware formatting (#204) 2026-03-05 11:41:59 +00:00
currencies.php feat(currencies): add Hong Kong Dollar (HKD) (#688) 2026-07-17 11:46:21 +00:00
database.php feat(console): add agent:db command for querying local and prod DB (#522) 2026-06-12 18:35:14 +02:00
filesystems.php Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
fortify.php Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
inertia.php Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
landing.php feat(landing): add signed auth links (#312) 2026-04-21 08:28:59 +01:00
logging.php fix(logging): keep laravel.log writable across container UIDs (#451) 2026-05-29 15:10:50 +02:00
mail.php feat(mail): use AWS SES for email delivery (#422) 2026-05-25 10:59:57 +02:00
mcp.php fix(mcp): serve OAuth authorize on a dedicated host so the PWA can't capture it (#709) 2026-07-21 13:51:03 +02:00
passport.php feat(mcp): add OAuth 2.1 for Claude Desktop & ChatGPT connectors (Phase 3) (#691) 2026-07-17 19:10:48 +02:00
pennant.php Add Cashflow Analytics Feature (#49) 2026-01-05 13:06:50 +01:00
queue.php fix(queue): raise retry_after above the longest job timeout (PHP-LARAVEL-2D) (#645) 2026-07-05 09:31:23 +00:00
sanctum.php feat(mcp): read-only MCP server for Pro accounts (#689) 2026-07-17 16:54:15 +02:00
sentry.php fix(sentry): only report errors in production (#467) 2026-06-01 12:41:31 +02:00
services.php feat(ai): add weekly AI-suggestions cohort report (#530) 2026-06-13 23:23:34 +02:00
session.php Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
subscriptions.php feat(subscriptions): trial/pricing A/B/C experiment (#600) 2026-06-27 18:00:15 +02:00