Skip to content
runlot
ReferenceAPIoauth

oauth

Covers 7 API operations in the oauth category.

MethodPathDescription
GET/.well-known/oauth-authorization-serverAuthorization server metadata (RFC 8414)
GET/.well-known/jwks.jsonThe access tokens' public keys
POST/v1/oauth/authorizeApprove a connected app and mint an authorization code
POST/oauth/tokenExchange a code, or refresh (RFC 6749)
POST/oauth/revokeSign a connected app out (RFC 7009)
GET/v1/oauth/grantsConnected apps
DELETE/v1/oauth/grants/{sid}Remove a connected app

GET /.well-known/oauth-authorization-server

What a client reads before it has any credential, so it is open by definition.

authorization_endpoint points at the dashboard, not at this API: the authorization step has to see the user's login session, which lives in the browser (docs/studio.md §8.1). runlot_access_token_audience is not in RFC 8414 — it is here so a resource server learns the aud it must require from the issuer rather than from a second configured value that can disagree.

operationId oauthMetadata

Status codeDescriptionResponse body
200The metadata documentobject
503Connected-app sign-in is not configured on this deploymentError

GET /.well-known/jwks.json

Every non-retired signing key. Two are published during a rotation, which is the whole reason this is a set: a verifier that cached one key would refuse tokens minted with the other. Cacheable for a minute, and no longer — a stale copy refuses fresh tokens.

operationId oauthJwks

Status codeDescriptionResponse body
200The key setobject

POST /v1/oauth/authorize

Called by the dashboard's /oauth/authorize screen with the user's login session. A personal access token is refused whatever its scopes: a credential must never be able to widen itself into a longer-lived one.

The parameters carry OAuth's own names rather than this document's camelCase, because the screen forwards the query string it was handed.

operationId oauthAuthorize

Request body: application/json · object

Status codeDescriptionResponse body
200Approved. The browser is sent to redirect.object
400——
401——

POST /oauth/token

Form-encoded, not JSON — RFC 6749 §4.1.3, and what every client library sends.

The failures are RFC 6749 §5.2's body, not this document's error envelope, because these two endpoints are read by generic OAuth clients that cannot parse ours.

Refresh tokens rotate: using one invalidates it and returns the next. Rate limited per client and per address (429).

operationId oauthToken

Request body: application/x-www-form-urlencoded · object

Status codeDescriptionResponse body
200A new access token, and the next refresh tokenOAuthTokenResponse
400RFC 6749 §5.2OAuthError
429Too many attempts from this client or this addressOAuthError
503Connected-app sign-in is not configured on this deploymentOAuthError

POST /oauth/revoke

Form-encoded. It answers 200 for a token it does not know — RFC 7009 §2.2 requires it, and the reason is that any other answer turns the endpoint into an oracle for which tokens exist.

Revoking a refresh token revokes the whole grant, not one rotation generation: "sign out in Studio" means the device is gone from Connected apps too (docs/studio.md §8.4). Rate limited per client and per address (429).

operationId oauthRevoke

Request body: application/x-www-form-urlencoded · object

Status codeDescriptionResponse body
200Revoked, or the token was unknown — the two are deliberately the same answer—
400RFC 6749 §5.2OAuthError
429Too many attempts from this client or this addressOAuthError

GET /v1/oauth/grants

What can reach this account right now (docs/studio.md §8.4). Revoked grants are not listed: a list that keeps dead rows makes the answer a filter the reader has to apply.

Session only, for POST /v1/oauth/authorize's reason.

operationId listOAuthGrants

Status codeDescriptionResponse body
200The grantsobject
401——

DELETE /v1/oauth/grants/{sid}

Its refresh tokens die with it, its access token dies on the next request through the sid check, and the revocation reaches the Studio service through cp-core's feed — so a lent model drops at once rather than within the access token's fifteen minutes.

A grant that is not this user's is a 404, not a 403: telling a caller that somebody else's grant id exists is a probe for grant ids.

operationId revokeOAuthGrant

Status codeDescriptionResponse body
204Removed—
401——
404——

On this page