Skip to content

Improve SWICG ActivityPub API Basic Profile conformance for C2S#3328

Merged
pfefferle merged 3 commits into
trunkfrom
add/swicg-basic-profile-c2s-conformance
May 20, 2026
Merged

Improve SWICG ActivityPub API Basic Profile conformance for C2S#3328
pfefferle merged 3 commits into
trunkfrom
add/swicg-basic-profile-c2s-conformance

Conversation

@pfefferle
Copy link
Copy Markdown
Member

Fixes #

Proposed changes:

Three additive, backward-compatible changes to bring the OAuth-based Client-to-Server surface closer to the SWICG ActivityPub API Basic Profile:

  • Return activitypub_actor_id alongside the existing IndieAuth me field in token and introspect responses, so SWICG-aware clients can discover the authenticated actor under the spec property name. Same value for both fields; nothing is removed.
  • Accept canonical SWICG scope identifiers. Scope::validate() now collapses any activitypub:read:* to the internal read scope and any activitypub:write:* to write. The scopes_supported advertised at /oauth/authorization-server-metadata now includes the canonical aliases activitypub:read:all and activitypub:write:all alongside the existing read / write / follow / push / profile. Enforcement stays coarse — there is no per-activity-type access control yet.
  • Send Retry-After: 60 on all OAuth 429 rate-limit responses (token, authorize, register) per RFC 6585 §4, so clients can back off cleanly. The token controller threads this through the existing token_error() helper; the authorize and register controllers convert their WP_Error paths to WP_REST_Response via a small rate_limit_response() helper kept private to each controller.

FEDERATION.md adds the Basic Profile to the list of supported standards and documents the C2S behavior in the OAuth section.

Other information:

  • Have you written new tests for your changes, if applicable?

Testing instructions:

  • Enable the ActivityPub API option in Settings → ActivityPub.
  • Hit GET /wp-json/activitypub/1.0/oauth/authorization-server-metadata and confirm scopes_supported contains both read/write and activitypub:read:all/activitypub:write:all.
  • Drive the standard authorization-code + PKCE flow with a request like scope=activitypub:read:me:inbox and verify:
    • The token response includes both me and activitypub_actor_id, set to the same actor URI.
    • The granted scope in the response is read (collapsed from the canonical name).
  • Trigger the rate limiter by hammering /oauth/token, /oauth/authorize, or /oauth/clients past their per-minute caps and confirm the 429 response carries Retry-After: 60.
  • npm run env-test -- --group=oauth should pass (179/179 locally).

Changelog entry

Three entries already added under .github/changelog/. No new entry needed via the workflow.

Changelog Entry Details

Significance

  • Patch
  • Minor
  • Major

Type

  • Added - for new features
  • Changed - for changes in existing functionality

Message

C2S token responses now include activitypub_actor_id; canonical SWICG scope names are accepted; OAuth rate-limit responses send Retry-After.

Three additive, backward-compatible changes:

- Return `activitypub_actor_id` alongside `me` in token and introspect
  responses so SWICG-aware clients can discover the authenticated actor
  under the spec name (existing IndieAuth `me` is preserved).
- Normalize canonical SWICG scope identifiers in `Scope::validate()`:
  any `activitypub:read:*` collapses to the internal `read` scope and
  any `activitypub:write:*` collapses to `write`. Advertise both the
  internal scopes and the canonical aliases `activitypub:read:all` /
  `activitypub:write:all` in `scopes_supported`.
- Emit `Retry-After: 60` on all OAuth 429 rate-limit responses (token,
  authorize, register) per RFC 6585 §4 so clients can back off.

FEDERATION.md updated to list the Basic Profile under supported
standards.
Copilot AI review requested due to automatic review settings May 20, 2026 08:29
@pfefferle pfefferle self-assigned this May 20, 2026
@pfefferle pfefferle requested a review from a team May 20, 2026 08:29
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves the plugin’s OAuth-based Client-to-Server (C2S) behavior to better align with the SWICG ActivityPub API Basic Profile, while keeping changes additive/backward-compatible.

Changes:

  • Add activitypub_actor_id alongside IndieAuth me in token and introspection responses.
  • Accept canonical SWICG scope forms (activitypub:read:*, activitypub:write:*) by normalizing them to the existing coarse read/write scopes, and advertise canonical aliases in OAuth metadata.
  • Include Retry-After: 60 on OAuth 429 rate-limit responses (token, authorize, client registration), and document this support in FEDERATION.md.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/phpunit/tests/includes/rest/oauth/class-test-token-controller.php Asserts Retry-After on 429 and validates activitypub_actor_id parity with me in token/introspect responses.
tests/phpunit/tests/includes/rest/oauth/class-test-clients-controller.php Validates Retry-After for registration 429s and that metadata advertises canonical scope aliases.
tests/phpunit/tests/includes/rest/oauth/class-test-authorization-controller.php Validates Retry-After for authorize 429 responses.
tests/phpunit/tests/includes/oauth/class-test-scope.php Adds coverage for canonical SWICG scope normalization, deduping, and supported-scope advertisement.
includes/rest/oauth/class-token-controller.php Adds Retry-After header to token endpoint 429 error responses via token_error().
includes/rest/oauth/class-clients-controller.php Converts registration rate-limit WP_Error paths to 429 WP_REST_Response with Retry-After.
includes/rest/oauth/class-authorization-controller.php Converts authorization rate-limit WP_Error paths to 429 WP_REST_Response with Retry-After.
includes/oauth/class-token.php Adds activitypub_actor_id to token creation and introspection payloads (same value as me).
includes/oauth/class-server.php Switches scopes_supported metadata to Scope::supported() to include canonical aliases.
includes/oauth/class-scope.php Adds canonical alias support: normalize activitypub:read:*/activitypub:write:* to internal scopes and advertise aliases.
FEDERATION.md Documents Basic Profile (partial) and Retry-After behavior for OAuth rate limiting.
.github/changelog/swicg-basic-profile-token-fields Changelog entry for activitypub_actor_id addition.
.github/changelog/swicg-basic-profile-scope-aliases Changelog entry for canonical scope alias support and advertisement.
.github/changelog/oauth-rate-limit-retry-after Changelog entry for Retry-After on OAuth 429 responses.

Comment thread includes/rest/oauth/class-clients-controller.php
@pfefferle pfefferle merged commit 3d01f3f into trunk May 20, 2026
11 checks passed
@pfefferle pfefferle deleted the add/swicg-basic-profile-c2s-conformance branch May 20, 2026 09:45
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