Skip to content

Add support for Dynamic Client Registration (RFC 7591) #13

Description

@roborourke

Add an OAuth2 Dynamic Client Registration endpoint (RFC 7591) so clients can register themselves at /oauth2/register instead of requiring an admin to create an oauth2_client post by hand. This is the missing piece for MCP-style and other automated clients to onboard without manual setup, and pairs with #12 (discovery should advertise a registration_endpoint once this exists).

Clients are stored today as oauth2_client posts (inc/class-client.php): post_name is the client_id, post_status gates approval (draft → publish), and secret/type/redirect_uri live in post meta. DCR needs to register through that same model, so most of the work is a new endpoint plus filling in metadata fields the model doesn't capture yet.

Implementation plan:

  • Add Endpoints\Registration (inc/endpoints/class-registration.php), following the Endpoints\Token pattern, registering POST /oauth2/register in inc/endpoints/namespace.php.
  • Accept the RFC 7591 §2 metadata fields: redirect_uris, token_endpoint_auth_method, grant_types, response_types, client_name, client_uri, logo_uri, scope, contacts, tos_uri, policy_uri, jwks_uri. Extend Client::create() and add post meta keys for the ones not already stored (only type and redirect_uri exist today).
  • Validate per RFC 7591 §3.2.2: reject unknown grant_types/response_types, require redirect_uris (subject to Match redirect URIs exactly, not just scheme/host/port/path #7's exact-match rule), restrict token_endpoint_auth_method to none / client_secret_post / client_secret_basic.
  • Generate client_id the same way Client::create() does today; generate client_secret only when token_endpoint_auth_method isn't none (public client).
  • Return the RFC 7591 §3.2.1 response: client_id, client_secret (if issued), client_id_issued_at, client_secret_expires_at (0, matching that secrets don't expire elsewhere in this plugin), plus the metadata echoed back.
  • Decide the approval story and document it in the issue/PR: does a self-registered client land as post_status = draft like a manually-created one (blocking use until an admin approves it), or is it usable immediately? Open registration with immediate use is a spam/abuse vector worth deciding deliberately rather than defaulting into.
  • Add tests/test-registration-endpoint.php (pattern: tests/test-token-endpoint.php) covering a minimal valid registration, a missing/invalid redirect_uris, an unsupported grant_type, and the public-vs-confidential response shape.
  • Document the endpoint in docs/spec.md, which currently only covers OAuth 1.0a (also relevant to Replace the OAuth 1.0a documentation #10).

Out of scope for this issue, filed separately once this lands: RFC 7592 (the client configuration management protocol — GET/PUT/DELETE on a client's own registration via a registration_access_token).

Related: #1 (PKCE — self-registered public clients should get the same "Require PKCE" treatment), #3 (confidential client authentication — a DCR-issued client_secret needs somewhere real to be checked), #7 (redirect_uri matching), #12 (discovery should list registration_endpoint).

RFC: https://www.rfc-editor.org/rfc/rfc7591

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions