Gateway API - OAuth token auth and licence key fetch endpoints
I am building octobercms-cli, an open-source Ruby CLI that makes deploying OctoberCMS a single-command operation (third-party, not affiliated). The CLI wraps Kamal as the deployment engine and integrates with the OctoberCMS account API for licence management.
This issue documents the API surface I need the Gateway to expose for the CLI's first milestone. Everything below is currently absent or insufficient in the existing Gateway.
Background: why not just use HMAC auth?
The current Gateway uses HMAC (Rest-Key + Rest-Sign headers) as its account-level auth mechanism. This requires the user to copy an API key and a base64-decoded secret into the CLI, a poor UX and a security risk (secrets in shell history, config files). The CLI needs a browser-based OAuth-style flow that produces a short-lived bearer token, matching the UX of gh auth login and flyctl auth login.
Required additions
- OAuth-style CLI authorization flow
New endpoint: GET https://octobercms.com/cli/authorize
Query params:
- state — CSRF token generated by the CLI (random hex, 32 bytes)
- callback_port — the localhost port the CLI's HTTP listener is bound to
Flow:
- CLI opens the browser to this URL with state and callback_port.
- User authenticates in the browser (existing session or login).
- Gateway redirects to http://localhost:<callback_port>/callback?token=<bearer_token>&state=.
- CLI validates state matches, stores the token.
The token must be:
- A bearer token (not an HMAC key/secret pair)
- Scoped to read-only access: list projects, fetch licence keys — no write access to billing or account settings
- Associated with a TTL (suggested: 90 days) with a refresh mechanism
Why needed: octobercms-cli auth login — the browser-based first-time auth flow.
- Token introspection endpoint
New endpoint: POST /v1/auth/introspect
Auth: Authorization: Bearer
Response: { "valid": true, "account_email": "[email protected]", "scopes": ["projects:read", "licenses:read"], "expires_at": "2026-12-01T00:00:00Z" }
Why needed: octobercms-cli auth status and octobercms-cli doctor — verifying the stored token is still valid without requiring a full project fetch.
- Token revocation endpoint
New endpoint: POST /v1/auth/revoke
Auth: Authorization: Bearer
Body: { "token": "<token_to_revoke>" }
Response: 204 No Content
Why needed: octobercms-cli auth logout — must be able to invalidate the token server-side, not just delete the local file. Without this, a leaked token remains valid forever.
- Fetch licence key for a Project ID
New endpoint: GET /v1/projects/:project_id/license
Auth: Authorization: Bearer
Response: { "project_id": "abc123", "license_key": "XXXX-XXXX-XXXX-XXXX", "expires_at": "2027-01-01T00:00:00Z", "plan": "professional", "days_until_expiry": 243 }
Why needed: This is the critical missing piece. The current API is circular: project-level endpoints authenticate using the licence key (php-auth-pw header), so there is no way to retrieve the key if you don't already have it. The CLI fetches this key per-build (at octobercms-cli deploy time), injects it into the Docker build via BuildKit secret mount, then discards it — the key never lives in the project directory or image layers. Without this endpoint, the build-time secret-injection model cannot work.
This is also what octobercms-cli doctor uses to warn at 30 days before expiry and fail at expiry.
- Project list with licence health (bearer token variant)
The existing projects/list endpoint requires HMAC auth. I need this endpoint to also accept bearer tokens, and the response should include licence expiry data inline:
Updated response shape for projects/list (bearer auth): { "data": [ { "id": "abc123", "name": "My Site", "plan": "professional", "license_expires_at": "2027-01-01T00:00:00Z", "days_until_expiry": 243 } ], "cursor": "next_page_cursor" }
Why needed: octobercms-cli project list and the Project picker in octobercms-cli init — the CLI shows licence health inline so users see expiry warnings before they get to deploy time.
The hard dependency is Endpoint 4 (licence key fetch). This single endpoint is blocking the entire build-time secret-injection architecture. Endpoints 1–3 (OAuth flow) are next in priority.
Source: octobercms/october