feat(dashboard): OAuth client-credentials form (closes #2761 UI leg)#2808
Merged
Conversation
Closes the UI leg of #2761. Completes the server-side work in #2800. Adds a third option to the existing Auth-type select on dashboard-agents.html — "OAuth client credentials (machine-to-machine)" — alongside OAuth (auth-code) and bearer/basic. Selecting it reveals: - token_endpoint (URL, required) - client_id, client_secret (required, both accept `$ENV:ADCP_OAUTH_<NAME>` references) - scope, resource, audience (optional) - auth_method select (basic / body) Submit calls PUT /api/registry/agents/:encodedUrl/oauth-client-credentials (from #2800), validated server-side through the shared parseOAuthClientCredentialsInput. The "Auth configured" label distinguishes oauth_client_credentials from plain OAuth post-save. Verified via an isolated Playwright test that loads the real buildConnectForm + toggle + submit handlers, stubs fetch, drives the form, and asserts on the captured request. 16/16 assertions pass. Full in-browser validation against a running dev server is recommended before merge (requires WorkOS/PG/encryption-secret setup not available in this workspace). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…t review Three small fixes from the code + DX reviews on #2808: - CSS: add .agent-cc-save to the selector lists used by .agent-connect-save and .agent-oauth-start. Without this the new button inherits default browser styling instead of the branded primary-colored look. Flagged by code review. - Token endpoint field: add a hint line showing the Auth0 / Okta / Azure AD / Keycloak URL patterns so operators don't have to fish in their IdP console to remember the shape. - resource vs audience: add one-line hints under each field clarifying that resource (RFC 8707) is what Okta/Keycloak want and audience is Auth0's name for the same thing — operators routinely conflate these. - $ENV:ADCP_OAUTH_ prefix explanation: extend the heading hint to explain *why* the prefix is mandatory (server-side allowlist prevents a misconfigured agent from referencing unrelated env vars). Playwright test still passes (16/16 assertions) — these are text-only edits that don't change behavior. Not in this PR (filed as follow-ups): - Test-now dry-run button (#2809) - Structured error codes on credential-save endpoints (#2810) - Dedupe platform_type across auth-variant field groups (#2811) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
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.
Closes the UI leg of #2761. Completes the feature — server-side persistence and resolution landed in #2800.
What this PR adds
A third option on the agent-compliance page's Auth-type select — OAuth client credentials (machine-to-machine) — alongside the existing OAuth (authorization-code) and bearer/basic options. Selecting it reveals:
token_endpointclient_id$ENV:ADCP_OAUTH_<NAME>.client_secret$ENV:ADCP_OAUTH_<NAME>. Stored encrypted at rest.scoperesourceaudienceaudclaim).auth_methodbasic(HTTP Basic header, default, RFC 6749 §2.3.1 preferred) orbody(form fields).Submit fires
PUT /api/registry/agents/:encodedUrl/oauth-client-credentials(the endpoint from #2800), which runs the input through the sharedparseOAuthClientCredentialsInputvalidator — same rules (SSRF,$ENV:ADCP_OAUTH_allowlist, length limits) whether the save came from this form or the Addiesave_agenttool.The "Auth configured" label on the post-save state now distinguishes
oauth_client_credentialsfrom plain OAuth.Review cycle
Ran through code-reviewer, security-reviewer, and dx-expert. Addressed in this PR:
.agent-cc-saveto the CSS selector lists so the new button matches the branded primary-colored look of the other two save buttons.token_endpoint; one-line clarifications distinguishingresource(RFC 8707, Okta/Keycloak) fromaudience(Auth0'saudclaim); expanded$ENV:ADCP_OAUTH_hint to explain why the prefix is mandatory (server-side allowlist — prevents a misconfigured agent from referencing unrelated env vars)./csrf.jsfetch monkey-patch, no local guard needed).Deferred as follow-ups:
Verification
buildConnectForm+ toggle + submit handlers, stubsfetch, drives the form end-to-end, and asserts on the captured request./dashboard-agents.htmlincludes every new marker:OAuth client credentialsoption,auth-cc-fieldscontainer,cc_token_endpointinput,$ENV:ADCP_OAUTH_policy hint, IdP URL patterns (Auth0/Okta/Azure AD/Keycloak), RFC 8707 resource hint,agent-cc-saveCSS class.npm run typecheckclean.Screenshot
Full-page screenshot of the empty-state dashboard served from Docker available at
.context/oauth-cc-dashboard.pnglocally; the form-visible render is covered by the isolated Playwright test.🤖 Generated with Claude Code