Skip to content

[OPIK-6666] [BE] feat: MCP OAuth dynamic client registration — RFC 7591 (PR 5/7)#6996

Open
LifeXplorer wants to merge 9 commits into
avinahradau/OPIK-6666-oauth-as-chunked-4from
avinahradau/OPIK-6666-oauth-as-chunked-5
Open

[OPIK-6666] [BE] feat: MCP OAuth dynamic client registration — RFC 7591 (PR 5/7)#6996
LifeXplorer wants to merge 9 commits into
avinahradau/OPIK-6666-oauth-as-chunked-4from
avinahradau/OPIK-6666-oauth-as-chunked-5

Conversation

@LifeXplorer

@LifeXplorer LifeXplorer commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Details

PR 5 of 7 splitting #6900 per review.

⛓️ Chained PR. Base is avinahradau/OPIK-6666-oauth-as-chunked-4 (PR #6995). Base retargets to main once PR-4 lands.

Item What
OAuthRegisterResource POST /oauth/register — RFC 7591 dynamic client registration for AI hosts; IP-bucketed rate limiting via RateLimitService
ClientRegistrationResponse response DTO
McpOAuthBundle now also disables OAuthRegisterResource when flag off
OAuthRegisterResourceTest coverage

Note: adapted to PR-1's slimmed McpOAuthClient (no createdAt). client_id_issued_at is optional (RFC 7591 §3.2.1) and is omitted from the response; the test asserts that.

Change checklist

  • User facing
  • Documentation update

Testing

  • mvn -o test-compile — green.

Documentation

No user-facing documentation changes required — internal MCP OAuth registration endpoint, not part of the public API surface.

Issues

🤖 Generated with Claude Code

PR 5 of 7 (chained on PR 4).

- OAuthRegisterResource: POST /oauth/register — self-registration for AI
  hosts, IP-bucketed rate limiting via RateLimitService
- ClientRegistrationResponse DTO
- McpOAuthBundle: also disables OAuthRegisterResource when flag is off
- OAuthRegisterResourceTest

Adapted to PR 1's slimmed McpOAuthClient (no createdAt): client_id_issued_at
is optional per RFC 7591 §3.2.1 and is omitted from the response.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@LifeXplorer LifeXplorer requested a review from a team as a code owner June 8, 2026 13:02
@github-actions github-actions Bot added java Pull requests that update Java code Backend tests Including test files, or tests related like configuration. labels Jun 8, 2026
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Backend Tests - Unit Tests

2 261 tests  +4   2 259 ✅ +4   1m 20s ⏱️ -1s
  301 suites +1       2 💤 ±0 
  301 files   +1       0 ❌ ±0 

Results for commit 0cece45. ± Comparison against base commit dcc8db5.

♻️ This comment has been updated with latest results.

@LifeXplorer LifeXplorer left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Opik reviewer (mined from your team's review history)

6 findings — 0 high · 2 medium · 4 low. Suppressed by team conventions: see suppressed.md.

React 👍/👎 on each comment — your feedback helps tune what it flags.

- Fix OAuthRegisterResourceTest: build resource in setUp() after stubbing
  config (was NPEing under @Injectmocks since LimitConfig moved to ctor)
- Key rate-limit bucket on last X-Forwarded-For hop (nginx-appended,
  unspoofable) instead of the attacker-controlled first hop
- Assert full ClientRegistrationResponse and 429 OAuthError body
- Emit Retry-After header on 429 from remaining TTL
- Extract RATE_LIMIT_BUCKET_PREFIX to dedupe the bucket literal
- Rename register_clientIdIssuedAtAlwaysOmitted; document throttle is
  intentionally independent of the global rateLimit.enabled flag

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
LifeXplorer and others added 3 commits June 8, 2026 20:55
…hunked-4' into avinahradau/OPIK-6666-oauth-as-chunked-5

# Conflicts:
#	apps/opik-backend/src/main/java/com/comet/opik/domain/mcpoauth/ClientRegistrationRequest.java
Base merge renamed McpOAuthClient.clientId to id; update the register
resource, response mapper, and test to the new accessor/builder.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

McpOAuthClient client = clientService.register(request);
ClientRegistrationResponse body = ClientRegistrationResponseMapper.INSTANCE.toResponse(client);
return Response.created(URI.create("/admin/mcp-oauth-clients/" + client.id()))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Response.created(URI.create("/admin/mcp-oauth-clients/" + client.id())) returns a relative Location; should we build it from uriInfo.getAbsolutePathBuilder().path(client.id()).build() so it’s absolute and deterministic?

Severity

Want Baz to fix this for you? Activate Fixer

Other fix methods

Fix in Cursor

Prompt for AI Agents
Before applying, verify this suggestion against the current code. In
apps/opik-backend/src/main/java/com/comet/opik/api/resources/oauth/OAuthRegisterResource.java
around line 83, the create endpoint returns
Response.created(URI.create("/admin/mcp-oauth-clients/" + client.id())) which sets the
201 Location header to a relative URI. Refactor this so Location is an absolute,
deterministic URI built from the current request context—use
uriInfo.getAbsolutePathBuilder() (and append the client id path segment) to build the
URI for the Location header. Ensure the Location value is absolute (includes
scheme/host) and matches the API’s intended `/admin/mcp-oauth-clients/{id}` route.

Match the @Tag/@Operation/@apiresponse pattern used by the sibling
OAuth resources so the registration endpoint appears in the API docs.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Backend java Pull requests that update Java code tests Including test files, or tests related like configuration.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant