Skip to content

fix(api): OAuth dynamic client registration fails for Claude Desktop - #8114

Merged
khvn26 merged 4 commits into
mainfrom
fix/dcr-native-client-redirect-uris
Jul 28, 2026
Merged

fix(api): OAuth dynamic client registration fails for Claude Desktop#8114
khvn26 merged 4 commits into
mainfrom
fix/dcr-native-client-redirect-uris

Conversation

@khvn26

@khvn26 khvn26 commented Jul 27, 2026

Copy link
Copy Markdown
Member

Thanks for submitting a PR! Please check the boxes below:

  • I have read the Contributing Guide.
  • I have added information to docs/ if required so people know about the feature.
  • I have filled in the "Changes" section below.
  • I have filled in the "How did you test this code" section below.

Changes

Closes #8113.

In this PR, we:

  1. Allow custom protocols as part of OAuth redirect URLs. This enables MCP usage in e.g. Claude Desktop.

  2. Map rest-framework serializer errors to errors conformant to RFC 7591.

How did you test this code?

Added unit tests reproducing the custom schema and error parsing issues.

Accept private-use scheme redirect URIs (RFC 8252 §7.1) in DCR,
blocklisting browser-executable schemes. Fix the KeyError 500 when an
invalid redirect URI is not first in the list, and stop leaking the
ErrorDetail repr into error_description. Error formatting is extracted
to mappers.map_drf_error_to_rfc7591_error_body.

beep boop
@khvn26
khvn26 requested a review from a team as a code owner July 27, 2026 16:12
@khvn26
khvn26 requested review from emyller and removed request for a team July 27, 2026 16:12
@vercel

vercel Bot commented Jul 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

3 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs Ignored Ignored Preview Jul 27, 2026 4:46pm
flagsmith-frontend-preview Ignored Ignored Preview Jul 27, 2026 4:46pm
flagsmith-frontend-staging Ignored Ignored Preview Jul 27, 2026 4:46pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Dynamic client registration now accepts custom-scheme redirect URIs through serializer input handling while applying expanded scheme, host, fragment, and format validation. Forbidden schemes are rejected, and HTTP is restricted to loopback hosts. DRF validation errors are mapped through a new RFC 7591 mapper with recursive message extraction, and registration tests cover the updated URI cases and error responses.

Estimated code review effort: 3 (Moderate) | ~25 minutes


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added api Issue related to the REST API fix labels Jul 27, 2026
@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Docker builds report

Image Build Status Security report
ghcr.io/flagsmith/flagsmith-e2e:pr-8114 Finished ✅ Skipped
ghcr.io/flagsmith/flagsmith-api-test:pr-8114 Finished ✅ Skipped
ghcr.io/flagsmith/flagsmith-frontend:pr-8114 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-api:pr-8114 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-private-cloud:pr-8114 Finished ✅ Results
ghcr.io/flagsmith/flagsmith:pr-8114 Finished ✅ Results

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 740120c7-5c71-44aa-b938-140fd1f19f1f

📥 Commits

Reviewing files that changed from the base of the PR and between 4d5fff8 and 1a4baee.

📒 Files selected for processing (6)
  • api/oauth2_metadata/mappers.py
  • api/oauth2_metadata/serializers.py
  • api/oauth2_metadata/services.py
  • api/oauth2_metadata/views.py
  • api/tests/unit/oauth2_metadata/test_dcr.py
  • api/tests/unit/oauth2_metadata/test_services.py

Comment thread api/oauth2_metadata/services.py Outdated
Comment thread api/tests/unit/oauth2_metadata/test_dcr.py
@codecov

codecov Bot commented Jul 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.70%. Comparing base (96d20b5) to head (e38799d).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #8114   +/-   ##
=======================================
  Coverage   98.69%   98.70%           
=======================================
  Files        1525     1526    +1     
  Lines       60607    60636   +29     
=======================================
+ Hits        59819    59848   +29     
  Misses        788      788           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor
✅ private-cloud · depot-ubuntu-latest-16 — run #18752 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  2 passed

Details

stats  2 tests across 2 suites
duration  36.9 seconds
commit  e38799d
info  🔄 Run: #18752 (attempt 1)

🗂️ Previous results
✅ private-cloud · depot-ubuntu-latest-arm-16 — run #18752 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  3 passed

Details

stats  3 tests across 3 suites
duration  1 minute, 4 seconds
commit  e38799d
info  🔄 Run: #18752 (attempt 1)

✅ oss · depot-ubuntu-latest-16 — run #18752 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  42.9 seconds
commit  e38799d
info  🔄 Run: #18752 (attempt 1)

✅ oss · depot-ubuntu-latest-arm-16 — run #18752 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  45.2 seconds
commit  e38799d
info  🔄 Run: #18752 (attempt 1)

✅ private-cloud · depot-ubuntu-latest-arm-16 — run #18751 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  2 passed

Details

stats  2 tests across 2 suites
duration  1 minute, 12 seconds
commit  c02b858
info  🔄 Run: #18751 (attempt 1)

✅ private-cloud · depot-ubuntu-latest-16 — run #18751 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  22 passed
skipped  1 skipped

Details

stats  23 tests across 18 suites
duration  1 minute, 30 seconds
commit  c02b858
info  🔄 Run: #18751 (attempt 1)

Skipped tests

firefox › tests/onboarding-tests.pw.ts › Onboarding › New user connects via the single-page onboarding flow @oss

✅ oss · depot-ubuntu-latest-arm-16 — run #18751 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  41.8 seconds
commit  c02b858
info  🔄 Run: #18751 (attempt 1)

✅ oss · depot-ubuntu-latest-16 — run #18751 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  38 seconds
commit  c02b858
info  🔄 Run: #18751 (attempt 1)

✅ private-cloud · depot-ubuntu-latest-16 — run #18750 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  2 passed

Details

stats  2 tests across 2 suites
duration  35.5 seconds
commit  19ad348
info  🔄 Run: #18750 (attempt 1)

✅ private-cloud · depot-ubuntu-latest-arm-16 — run #18750 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  35.8 seconds
commit  19ad348
info  🔄 Run: #18750 (attempt 1)

✅ oss · depot-ubuntu-latest-arm-16 — run #18750 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  45.6 seconds
commit  19ad348
info  🔄 Run: #18750 (attempt 1)

✅ oss · depot-ubuntu-latest-16 — run #18750 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  41.1 seconds
commit  19ad348
info  🔄 Run: #18750 (attempt 1)

@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Visual Regression

19 screenshots compared. See report for details.
View full report

DRF CharField coerces integers, so the child-field-error case never
produced the index-keyed dict shape; a blank string does. Restructure
_first_error_message as a loop so there is no unreachable fallback.

beep boop
@github-actions github-actions Bot added fix and removed fix labels Jul 27, 2026
urlparse raises ValueError on inputs like https://[::1, which escaped as
a 500. Catch it, and reject http(s) redirect URIs without a hostname
(e.g. https:///callback).

beep boop
@github-actions github-actions Bot added fix and removed fix labels Jul 27, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 85ddb5c5-dcd3-4c44-b044-2df11dedddc6

📥 Commits

Reviewing files that changed from the base of the PR and between 19ad348 and c02b858.

📒 Files selected for processing (2)
  • api/oauth2_metadata/services.py
  • api/tests/unit/oauth2_metadata/test_services.py

Comment thread api/oauth2_metadata/services.py
urlparse defers port validation to attribute access, and
django-oauth-toolkit reads .port on stored redirect URIs during
authorisation — a URI like https://example.com:not-a-port/callback
registered fine, then crashed the authorise flow.

beep boop
@github-actions github-actions Bot added fix and removed fix labels Jul 27, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
api/oauth2_metadata/services.py (1)

53-58: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Recognise the full loopback address range.

127.0.0.2 and other 127.0.0.0/8 addresses are valid loopback addresses, but this exact-match list rejects them. Use ipaddress.ip_address(host).is_loopback while retaining the localhost special case, and add a regression test for another 127.x.x.x address.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 8d7b847f-939c-43cd-8d97-bb356b0a5300

📥 Commits

Reviewing files that changed from the base of the PR and between c02b858 and e38799d.

📒 Files selected for processing (2)
  • api/oauth2_metadata/services.py
  • api/tests/unit/oauth2_metadata/test_services.py

Comment thread api/oauth2_metadata/mappers.py
@khvn26
khvn26 merged commit aecbbb6 into main Jul 28, 2026
34 checks passed
@khvn26
khvn26 deleted the fix/dcr-native-client-redirect-uris branch July 28, 2026 09:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api Issue related to the REST API fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OAuth dynamic client registration fails for Claude Desktop

4 participants