Skip to content

GET /oauth/clients

The workspace's registered third-party apps

The client registry an administrator manages: every app that may ask people here for bounded access. The secret of a confidential client is not among the fields - it was answered once, at registration.

Responses

  • 200 The clients
  • 4XX An error per RFC 9457 Problem
Example bash
curl -X GET "$HUBTASK_URL/oauth/clients" \  -H "Authorization: Bearer $HUBTASK_TOKEN"

POST /oauth/clients

Register a third-party app

A name, the exact redirect URIs it may be sent back to, and whether it can keep a secret. A public client - a native or single-page app - gets no secret and must bring PKCE to every authorization (RFC 7636); a confidential client gets one, in clear, for the only time, stored as a hash under its own purpose label. Redirect URIs match exactly, byte for byte: a prefix or wildcard match is how authorization codes end up on attacker-controlled pages.

Headers

NameTypeRequiredDescription
Idempotency-Keystring (uuid) optionalA UUID; identical requests return the same result for 24 h.

Request body application/json — OauthClientCreate

NameTypeRequiredDescription
namestring
  • minLength: 1
  • maxLength: 200
requiredWhat people read on the consent screen and in their grant list.
redirect_urisarray of string (uri) requiredMatched exactly, byte for byte, at authorization and at exchange.
confidentialboolean requiredTrue for an app that can keep a secret on a server; false for a native or single-page app, which gets none and must bring PKCE.

Responses

  • 201 Registered, with the secret - where there is one - shown for the only time OauthClientSecret
  • 4XX An error per RFC 9457 Problem
Example bash
curl -X POST "$HUBTASK_URL/oauth/clients" \  -H "Authorization: Bearer $HUBTASK_TOKEN" \  -H "Idempotency-Key: $(uuidgen)" \  -H "Content-Type: application/json" \  -d '{  "name": "string",  "redirect_uris": [    "https://example.org"  ],  "confidential": true}'

GET /oauth/clients/{clientId}

What an app is called, for the person being asked to allow it

The half of a registered client a consent screen needs: its name. Any signed-in member of the workspace may read it, and that is the point - the person deciding whether to allow an app is usually not an administrator, and a consent screen that cannot name the app is a screen that asks somebody to approve an identifier. That is the shape a phishing attempt wants. Deliberately narrower than the listing. The registered redirect URIs and whether the client is confidential are the administrator's business and are answered by GET /oauth/clients behind the permission that manages members; nothing here helps somebody enumerate the workspace's apps, because reading one requires already knowing its identifier - which the authorization request the reader arrived with already carries.

Path parameters

NameTypeRequiredDescription
clientIdstring (uuid) required

Responses

Example bash
curl -X GET "$HUBTASK_URL/oauth/clients/{clientId}" \  -H "Authorization: Bearer $HUBTASK_TOKEN"

DELETE /oauth/clients/{clientId}

Remove a third-party app

Removes the client and revokes every grant that pointed at it: the sessions those grants leashed refuse on their next request. What people allowed the app is withdrawn with the app, because a grant to a client nobody can name is a door with no label.

Path parameters

NameTypeRequiredDescription
clientIdstring (uuid) required

Responses

  • 204 Removed
  • 4XX An error per RFC 9457 Problem
Example bash
curl -X DELETE "$HUBTASK_URL/oauth/clients/{clientId}" \  -H "Authorization: Bearer $HUBTASK_TOKEN"

POST /oauth/authorize

Consent to an app's request for bounded access

The authorization endpoint, headless: the signed-in person - never a token, a person - names the client, the exact redirect URI, the scopes from this installation's own catalogue, and the PKCE challenge, and receives the single-use code the app will exchange. The consent is recorded as a grant the person can see and revoke beside their sessions; the web application's consent screen calls exactly this. A public client without PKCE is refused; S256 is the only accepted method - plain would put the verifier on the wire twice.

Request body application/json — OauthAuthorization

NameTypeRequiredDescription
client_idstring (uuid) required
redirect_uristring (uri) required
scopesarray of string requiredFrom this installation's own catalogue - the scopes descriptors already declare, no parallel vocabulary.
code_challengestring requiredBASE64URL(SHA256(code_verifier)), RFC 7636.
code_challenge_methodstring
  • S256
required
statestring, or null
  • maxLength: 512
optionalEchoed back untouched, for the client's own CSRF binding.

Responses

  • 201 Consented, with the code shown for the only time OauthCode
  • 4XX An error per RFC 9457 Problem
Example bash
curl -X POST "$HUBTASK_URL/oauth/authorize" \  -H "Authorization: Bearer $HUBTASK_TOKEN" \  -H "Content-Type: application/json" \  -d '{  "client_id": "018f6e2a-2b7c-7c1e-9b1a-3d5e6f7a8b9c",  "redirect_uri": "https://example.org",  "scopes": [    "string"  ],  "code_challenge": "string",  "code_challenge_method": "S256",  "state": "string"}'

POST /oauth/token

Exchange the code for the pair

The token endpoint. Public the way sign-in is: what authenticates is in the body - the single-use code, the PKCE verifier whose S256 hash has to equal the challenge the code was minted under, and, for a confidential client, the secret. A code replayed after exchange is refused; the redirect URI has to repeat the authorization's, exactly. The answer is the same pair sign-in mints, leashed to the grant: revoking the grant refuses the pair on its next request, exactly as refresh reuse would. Refresh happens at /auth/sessions:refresh, because it is the same machinery. The body is JSON; the form encoding of RFC 6749 is not accepted.

Request body application/json — OauthTokenRequest

NameTypeRequiredDescription
grant_typestring
  • authorization_code
required
codestring required
redirect_uristring (uri) requiredHas to repeat the authorization's, exactly.
client_idstring (uuid) required
code_verifierstring, or null
  • minLength: 43
  • maxLength: 128
optionalRFC 7636's verifier.
client_secretstring, or null optionalThe confidential client's credential.

Responses

Example bash
curl -X POST "$HUBTASK_URL/oauth/token" \  -H "Content-Type: application/json" \  -d '{  "grant_type": "authorization_code",  "code": "string",  "redirect_uri": "https://example.org",  "client_id": "018f6e2a-2b7c-7c1e-9b1a-3d5e6f7a8b9c",  "code_verifier": "string",  "client_secret": "string"}'

GET /oauth/grants

The apps the caller has allowed, and what

One's own grants, newest first: which client, which scopes, when it was allowed and when it last acted. Never anybody else's - what a person allowed is theirs to see and to withdraw, the session listing's reasoning.

Responses

  • 200 The grants
  • 4XX An error per RFC 9457 Problem
Example bash
curl -X GET "$HUBTASK_URL/oauth/grants" \  -H "Authorization: Bearer $HUBTASK_TOKEN"

DELETE /oauth/grants/{grantId}

Withdraw what an app was allowed

Immediate: every session the grant leashed refuses on its next request, the way a revoked session's pair does. Somebody else's grant is not found rather than forbidden; revoking twice is not an error.

Path parameters

NameTypeRequiredDescription
grantIdstring (uuid) required

Responses

  • 204 Withdrawn
  • 4XX An error per RFC 9457 Problem
Example bash
curl -X DELETE "$HUBTASK_URL/oauth/grants/{grantId}" \  -H "Authorization: Bearer $HUBTASK_TOKEN"