Skip to content

feat(site): add OAuth2 dynamic client registration toggle to deployment settings#27480

Draft
BobbyHo wants to merge 1 commit into
coder-eng-3056-dcr-flagfrom
coder-eng-3062-dcr-flag-ui
Draft

feat(site): add OAuth2 dynamic client registration toggle to deployment settings#27480
BobbyHo wants to merge 1 commit into
coder-eng-3056-dcr-flagfrom
coder-eng-3062-dcr-flag-ui

Conversation

@BobbyHo

@BobbyHo BobbyHo commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Important

Do not merge before #27316. This branch is stacked on
coder-eng-3056-dcr-flag (the head branch of #27316), so this PR's
base is set to that branch instead of main, keeping the diff here
to only the UI changes. Once #27316 merges, retarget this PR's base
to main (or rebase) before merging.

Adds the admin-controlled OAuth2 Dynamic Client Registration setting
from #27316 (GET/PUT /api/v2/oauth2-provider/settings) to the
OAuth2 Applications deployment settings page, since it was previously
only reachable via the API or coder oauth2-provider dcr enable|disable.

Enabling the toggle requires confirming a warning dialog, since it lets
any OAuth2 client self-register against the deployment without prior
admin approval (RFC 7591). Disabling is immediate, no confirmation.

Visibility and editability are gated on the same ResourceDeploymentConfig
RBAC checks the endpoint itself enforces (viewDeploymentConfig /
editDeploymentConfig), not a separate hardcoded check.

Closes #27432

Screenshots

Default (disabled):
image

Enabling (confirmation dialog):

image

Enabled:

image

…nt settings

Surfaces the admin-controlled DCR setting from GET/PUT
/api/v2/oauth2-provider/settings (added in #27316) on the OAuth2
Applications deployment settings page. Enabling the switch requires
confirming a warning dialog, since it lets any client self-register
against the deployment per RFC 7591; disabling is immediate.
@linear-code

linear-code Bot commented Jul 24, 2026

Copy link
Copy Markdown

ENG-3062

@BobbyHo

BobbyHo commented Jul 24, 2026

Copy link
Copy Markdown
Contributor Author

Backend verification

Manually verified against the local dev deployment (embedded Postgres + coderd)
that toggling the switch in the UI actually round-trips through the real
GET/PUT /api/v2/oauth2-provider/settings endpoints and persists to
site_configs, across three independent layers: the database, the API, and
the audit log.

Default state (disabled)

Postgres:

$ PGPASSWORD="$(cat .coderv2/postgres/password)" \
  psql -h localhost -p "$(sed -n '4p' .coderv2/postgres/data/postmaster.pid)" -U coder -d coder \
  -c "SELECT key, value FROM site_configs WHERE key = 'oauth2_dcr_enabled';"

        key         | value
--------------------+-------
 oauth2_dcr_enabled | false
(1 row)

API:

$ TOKEN=$(cat .coderv2/session)
$ curl -s http://127.0.0.1:3000/api/v2/oauth2-provider/settings \
  -H "Coder-Session-Token: $TOKEN"

{"dynamic_client_registration_enabled":false}

After enabling via the UI (clicked the switch, confirmed the warning dialog)

Audit log (GET /api/v2/audit?q=resource_type:oauth2_provider_settings):

{
    "id": "330e1fc8-046b-43de-b658-6b293a7a6c54",
    "time": "2026-07-23T16:58:06.761606-05:00",
    "resource_type": "oauth2_provider_settings",
    "action": "write",
    "diff": {
        "dynamic_client_registration_enabled": {
            "old": false,
            "new": true,
            "secret": false
        }
    },
    "status_code": 200,
    "description": "{user} updated oauth2 provider settings {target}",
    "user": {
        "username": "admin",
        "roles": [{ "name": "owner", "display_name": "Owner" }]
    }
}

Postgres:

        key         | value
--------------------+-------
 oauth2_dcr_enabled | true
(1 row)

API:

$ curl -s http://127.0.0.1:3000/api/v2/oauth2-provider/settings \
  -H "Coder-Session-Token: $TOKEN"

{"dynamic_client_registration_enabled":true}

After disabling via the UI (no confirmation dialog, disable is immediate)

Audit log:

{
    "id": "1f702c97-a2e7-4f4e-afaf-f99cd4ced4b8",
    "time": "2026-07-23T16:58:19.810326-05:00",
    "resource_type": "oauth2_provider_settings",
    "action": "write",
    "diff": {
        "dynamic_client_registration_enabled": {
            "old": true,
            "new": false,
            "secret": false
        }
    },
    "status_code": 200,
    "description": "{user} updated oauth2 provider settings {target}",
    "user": {
        "username": "admin",
        "roles": [{ "name": "owner", "display_name": "Owner" }]
    }
}

Postgres:

        key         | value
--------------------+-------
 oauth2_dcr_enabled | false
(1 row)

API:

{"dynamic_client_registration_enabled":false}

The enable (16:58:06, false → true) and disable (16:58:19, true → false)
audit entries are 13 seconds apart and in the correct order, matching the
enable-then-disable sequence performed in the UI. Each transition is
independently confirmed at the database, API, and audit layers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant