Skip to content

feat(mau): make token issuance and revocation identity-safe - #461

Open
ttypic wants to merge 1 commit into
integration/mau-client-id-flagfrom
integration/mau-fix-token-issuance
Open

ttypic wants to merge 1 commit into
integration/mau-client-id-flagfrom
integration/mau-fix-token-issuance

Conversation

@ttypic

@ttypic ttypic commented Oct 1, 2026 •

Copy link
Copy Markdown
  • auth issue-ably-token / issue-jwt-token resolve the token's client
    ID through one helper: --client-id, else the client ID the CLI acts
    as. "*" is refused, and "none" still issues an anonymous token but
    warns that apps requiring identified clients reject it.
  • Token output always states the identity: Client ID: anonymous in
    human output and clientId: null in JSON, rather than omitting it.
  • auth issue-jwt-token --client-type server adds the signed
    x-ably-clientType=server claim, which is the only way a
    token-authenticated client can be classified as a server.
  • auth revoke-token goes through the SDK's auth.revokeTokens instead
    of a hand-rolled HTTPS call to a hardcoded rest.ably.io, so it honours
    the configured endpoint and reports per-target failures.

- `auth issue-ably-token` / `issue-jwt-token` resolve the token's client
  ID through one helper: --client-id, else the client ID the CLI acts
  as. "*" is refused, and "none" still issues an anonymous token but
  warns that apps requiring identified clients reject it.
- Token output always states the identity: `Client ID: anonymous` in
  human output and `clientId: null` in JSON, rather than omitting it.
- `auth issue-jwt-token --client-type server` adds the signed
  `x-ably-clientType=server` claim, which is the only way a
  token-authenticated client can be classified as a server.
- `auth revoke-token` goes through the SDK's `auth.revokeTokens` instead
  of a hand-rolled HTTPS call to a hardcoded rest.ably.io, so it honours
  the configured endpoint and reports per-target failures.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
cli-web-cli Ready Ready Preview Oct 1, 2026 12:54pm UTC

Request Review

@claude-code-ably-assistant

Copy link
Copy Markdown

Walkthrough

This PR hardens the three ably auth token commands around client identity. Token issuance (issue-ably-token, issue-jwt-token) now routes all client-ID resolution through a single shared helper on the base command — refusing wildcards, warning on anonymous tokens, and always emitting the identity in output. revoke-token replaces a hand-rolled HTTPS call to a hardcoded rest.ably.io with the SDK's auth.revokeTokens(), so it honours the configured endpoint and surfaces per-target failures. A new --client-type server flag on issue-jwt-token adds the signed x-ably-clientType claim needed to exempt token-authenticated clients from MAU counting.

Changes

Area Files Summary
Commands src/commands/auth/issue-ably-token.ts Use resolveTokenClientId(); always show Client ID: anonymous (not omitted) in output; emit clientId: null in JSON
Commands src/commands/auth/issue-jwt-token.ts Same client-ID consolidation; add --client-type server flag that embeds x-ably-clientType: server JWT claim
Commands src/commands/auth/revoke-token.ts Replace ~70-line hand-rolled HTTPS implementation with rest.auth.revokeTokens(); handle per-target failure results; remove node:https import
Services src/services/client-identity.ts Minor copy tweak on the wildcard rejection error message
Base src/base-command.ts Add resolveTokenClientId() — validates via resolveClientIdentity(), refuses *, warns on none, falls back to CLI's own identity
Tests test/unit/commands/auth/revoke-token.test.ts Replace nock HTTP interception with getMockAblyRest() SDK mocks; update server-error test to cover per-target failure path
Tests test/unit/commands/auth/issue-ably-token.test.ts Add wildcard rejection test; add default-client-ID test; update --client-id none expectation to anonymous
Tests test/unit/commands/auth/issue-jwt-token.test.ts Add --client-type server claim tests; add wildcard rejection + default-identity tests; update anonymous display expectation
Test Helpers test/helpers/mock-ably-rest.ts Add revokeTokens mock to MockRestAuth interface

Review Notes

  • Output breaking change: --client-id none previously omitted the Client ID line entirely; it now always appears as Client ID: anonymous and emits a stderr warning. JSON output changes from omitting clientId to clientId: null. Callers parsing the human output or JSON should be aware.
  • Wildcard now rejected: --client-id * was silently accepted before; it now fails immediately with an error. Any existing scripts passing * will break.
  • revoke-token endpoint change: The old implementation hardcoded rest.ably.io. The new SDK call uses whatever endpoint is configured (e.g., sandbox, custom). This is strictly better but is a behavioural change worth noting for any environments that relied on the hardcoded host.
  • New JWT claim (--client-type server): The signed x-ably-clientType: server claim is the only way a token-authenticated client bypasses MAU counting. The flag currently only accepts "server" — the option list is a one-element enum, leaving room to add other types later without a breaking flag change.
  • nock no longer used in revoke-token tests: Tests now use the project-standard getMockAblyRest() mock rather than HTTP interception, which is more consistent. Verify nock isn't pulled in transitively only for these tests — if the package is unused elsewhere it could be dropped from dev dependencies.

@umair-ably
umair-ably added this pull request to stack #465 October 1, 2026 14:14
@ttypic
ttypic requested a review from umair-ably October 1, 2026 18:38

This branch was successfully deployed

1 active deployment
Preview — 47d5b857 Deployed Oct 1, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant