Fix OAuth consent CSP so Claude Desktop can connect to the MCP server#62
Merged
Conversation
The MCP OAuth consent screen silently failed in Claude's browser: approving it 302-redirects to https://claude.ai/api/mcp/auth_callback, but Chromium enforces form-action across the redirect chain and claude.ai wasn't allowlisted, so the authorization code never reached Claude. A second (cosmetic) console error came from django-oauth-toolkit's stock template loading Bootstrap from the dead netdna.bootstrapcdn.com, which style-src blocks. - Scope form-action to allow claude.ai/claude.com on the authorize view only (csp_update appends to the global policy), not site-wide. - Override the oauth2_provider templates with a self-contained, BrightBean-branded consent page that drops the external CDN. All DOT form mechanics (csrf token, hidden fields, name="allow") are preserved. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Fixes the MCP OAuth consent screen so Claude Desktop / claude.ai can complete the OAuth handshake against
https://studio.brightbean.xyz/api/v1/mcp. Two changes:claude.ai,claude.com) to theform-actionCSP directive — scoped to the/oauth/authorize/view only viacsp_update, not site-wide.Why?
Connecting Claude died on the consent screen with two CSP console errors:
form-action(the blocker): approving consent issues a 302 redirect tohttps://claude.ai/api/mcp/auth_callback. Chromium enforcesform-actionacross the entire redirect chain of a form submission, andclaude.aiwasn't in our allowlist — so the authorization code never reached Claude and the connection silently failed. (Chrome reports the violation against the form's own action URL for privacy, which is why the console error confusingly namedstudio.brightbean.xyzeven though'self'is allowed — the real blocked hop was the redirect out to claude.ai.)style-src(cosmetic): DOT's stockbase.htmlloads Bootstrap 2.3.2 from the long-deadnetdna.bootstrapcdn.com, which ourstyle-srcblocks → unstyled page + a second console error.Scoping the
form-actionrelaxation to the authorize view (rather than broadening the global policy) keeps every other form locked down. The redirect target is still validated by DOT against the registered client'sredirect_uri+ALLOWED_REDIRECT_URI_SCHEMES=["https"], so this does not introduce an open redirect. All DOT form mechanics (csrf token, hidden fields,name="allow") are preserved in the template override.How to test
pytest apps/oauth_server apps/mcp/tests/test_oauth_auth.py— OAuth flow, PKCE S256, DCR, WWW-Authenticate challenge.GET /oauth/authorize/?response_type=code&…&code_challenge_method=S256&scope=mcpand confirm the response'sform-actionnow containshttps://claude.ai https://claude.com, while a non-OAuth page does not (confirms the relaxation is scoped).netdnastyle-srcerror and theform-actionerror are gone, and the page renders on-brand. Click Authorize → redirects cleanly tohttps://claude.ai/api/mcp/auth_callback?code=….https://studio.brightbean.xyz/api/v1/mcpand confirm it connects and lists tools.Checklist
pytest) — 712 passedruff check .andruff format --check .) — both clean repo-wide