Skip to content

Implement RFC 7591 Dynamic Client Registration for ChatGPT OAuth#55

Merged
vitorhugo-java merged 1 commit into
mainfrom
claude/brave-ride-0e4b8d
Jun 9, 2026
Merged

Implement RFC 7591 Dynamic Client Registration for ChatGPT OAuth#55
vitorhugo-java merged 1 commit into
mainfrom
claude/brave-ride-0e4b8d

Conversation

@vitorhugo-java

Copy link
Copy Markdown
Owner

Summary

Adds support for RFC 7591 Dynamic Client Registration (DCR) to enable ChatGPT plugin OAuth integration. ChatGPT requires a DCR endpoint before it can complete the OAuth flow. This implementation provides a public /connect/register endpoint that allows clients to dynamically register without pre-configuration.

Key Changes

  • New DCR Controller (DynamicClientRegistrationController):

    • Implements RFC 7591 compliant /connect/register POST endpoint
    • Generates public clients (no secret) with PKCE requirement and authorization_code grant only
    • Validates redirect URIs (HTTPS required, except http://localhost for testing)
    • Supports scope negotiation with configurable allowed scopes
    • Implements per-IP rate limiting (5 registrations/minute) to prevent abuse
    • Generates unique client IDs with "dcr-" prefix to prevent collision with static clients
  • OIDC Discovery Updates (AuthorizationServerConfig):

    • Advertises registration_endpoint in .well-known/openid-configuration
    • Includes "none" in token_endpoint_auth_methods_supported for public client support
    • Implements userinfo mapper to return email and name from user repository for openid/profile scopes
  • Security Configuration (SecurityConfig):

    • Permits public access to /connect/register endpoint
    • Maintains protection for other OAuth endpoints
  • Comprehensive Integration Tests (DynamicClientRegistrationIT):

    • Validates OIDC discovery advertises DCR endpoint and "none" auth method
    • Tests successful registration with valid redirect URIs
    • Verifies scope negotiation (intersection of requested and allowed)
    • Confirms rejection of invalid URIs (non-HTTPS, missing, malformed)
    • Validates per-IP rate limiting enforcement
    • Tests default scope behavior when none requested

Implementation Details

  • Registered clients are configured as public (ClientAuthenticationMethod.NONE) with PKCE required
  • Rate limiting uses a thread-safe ConcurrentHashMap with sliding-window per IP
  • Scope resolution falls back to default scopes when MCP is not configured
  • Client names are sanitized (max 100 chars) to prevent injection
  • Redirect URIs are validated and deduplicated
  • Token TTL and refresh token settings are configurable via McpOAuthProperties

https://claude.ai/code/session_01X74fzJo874vACX3PM9mrWn

Spring Authorization Server 1.5.x does not natively support DCR (RFC 7591),
so this adds a minimal manual implementation to unblock the ChatGPT OAuth flow.
ChatGPT requires DCR and treats its absence in the OIDC discovery document as
a hard error ("There was a problem connecting").

Changes:
- DynamicClientRegistrationController: POST /connect/register that registers
  public PKCE-required clients (no secret, authorization_code only). Per-IP
  rate limit of 5/min prevents DB flooding. Redirect URIs must use HTTPS or
  http://localhost. Scopes are validated against the MCP allowed-scope list.
  Statically configured GPT/MCP clients are never overridden because the server
  always generates the client_id ("dcr-<uuid>") and ignores any client-provided
  value.
- AuthorizationServerConfig: OIDC discovery now advertises registration_endpoint
  and ensures "none" appears in token_endpoint_auth_methods_supported. Also adds
  a userInfoMapper so /userinfo returns sub, email, and name (loaded from
  UserRepository) instead of just sub.
- SecurityConfig: permits /connect/register without authentication.
- DynamicClientRegistrationIT: integration tests covering discovery doc, happy
  path, scope intersection, redirect_uri validation, and rate limiting.

https://claude.ai/code/session_01X74fzJo874vACX3PM9mrWn
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown

Qodana for JVM

3 new problems were found

Inspection name Severity Problems
Nullability and data flow problems 🔶 Warning 1
Mismatched query and update of 'StringBuilder' 🔶 Warning 1
Simplifiable conditional expression 🔶 Warning 1
View the detailed Qodana report

To be able to view the detailed Qodana report, you can either:

To get *.log files or any other Qodana artifacts, run the action with upload-result option set to true,
so that the action will upload the files as the job artifacts:

      - name: 'Qodana Scan'
        uses: JetBrains/qodana-action@v2025.3.2
        with:
          upload-result: true
Contact Qodana team

Contact us at qodana-support@jetbrains.com

@vitorhugo-java vitorhugo-java merged commit 23b52a0 into main Jun 9, 2026
6 checks passed
@vitorhugo-java vitorhugo-java deleted the claude/brave-ride-0e4b8d branch June 9, 2026 12:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants