Summary
After clicking "Allow" on the MCP OAuth consent screen (/api/mcp/oauth/authorize), the page appears to hang — the browser never navigates back to the connecting client (tested with claude.ai as the MCP client).
Root cause
The app's Content-Security-Policy response header includes:
This blocks any cross-origin form submission/navigation target. If the consent-grant step redirects the browser back to the client's redirect_uri (e.g. https://claude.ai/api/mcp/auth_callback) via a client-rendered form rather than a server-side HTTP redirect (Location header on a 302/303 response), the browser silently blocks it under form-action 'self'.
Confirmed via server logs: the authorization is actually granted successfully server-side (mcp.oauth.authorize.granted), immediately followed by a CSP violation report hitting /api/monitoring/csp-report — but the browser never leaves the page.
Suggested fix
Either:
- Perform the consent-grant redirect as a real HTTP 302/303 response with a
Location header (not subject to CSP form-action at all), or
- If a form-based redirect is intentional, dynamically include the specific client's registered
redirect_uri origin in form-action for that response only.
Environment
- HealthLog
latest (ghcr.io/mbombeck/healthlog), self-hosted via the documented docker-compose.
- Reproduced with claude.ai as the MCP client, standard OAuth 2.1 + PKCE dynamic client registration flow.
- Workaround in place on our end: a reverse-proxy response-header rewrite that widens
form-action to also allow https://claude.ai — not a real fix, since it's specific to one known client and won't help other MCP clients (ChatGPT, etc.) hitting the same issue.
🤖 Generated with Claude Code
Summary
After clicking "Allow" on the MCP OAuth consent screen (
/api/mcp/oauth/authorize), the page appears to hang — the browser never navigates back to the connecting client (tested with claude.ai as the MCP client).Root cause
The app's
Content-Security-Policyresponse header includes:This blocks any cross-origin form submission/navigation target. If the consent-grant step redirects the browser back to the client's
redirect_uri(e.g.https://claude.ai/api/mcp/auth_callback) via a client-rendered form rather than a server-side HTTP redirect (Locationheader on a 302/303 response), the browser silently blocks it underform-action 'self'.Confirmed via server logs: the authorization is actually granted successfully server-side (
mcp.oauth.authorize.granted), immediately followed by a CSP violation report hitting/api/monitoring/csp-report— but the browser never leaves the page.Suggested fix
Either:
Locationheader (not subject to CSPform-actionat all), orredirect_uriorigin inform-actionfor that response only.Environment
latest(ghcr.io/mbombeck/healthlog), self-hosted via the documented docker-compose.form-actionto also allowhttps://claude.ai— not a real fix, since it's specific to one known client and won't help other MCP clients (ChatGPT, etc.) hitting the same issue.🤖 Generated with Claude Code