SharkAuth API — OAuth 2.1 Endpoints
All OAuth endpoints live under /oauth/* and follow RFC 6749 / RFC 9449 semantics. Errors use the RFC 6749 §5.2 shape {error, error_description, error_uri}, not the admin envelope. Compatible with any standard OAuth 2.1 client library.
Dynamic Client Registration
POST /oauth/register — Register a client (RFC 7591)
Auth: None (open registration — protect with network policy in production)
Request:
Response 201 Created:
Error 400:
GET /oauth/register/{client_id} — Read client (RFC 7592)
Auth: Authorization: Bearer <registration_access_token>
Response 200: Client metadata object (same shape as register response, without client_secret).
PUT /oauth/register/{client_id} — Update client (RFC 7592)
Auth: Authorization: Bearer <registration_access_token>
Request: Full client metadata object (replacement, not partial patch).
Response 200: Updated client metadata.
DELETE /oauth/register/{client_id} — Delete client (RFC 7592)
Auth: Authorization: Bearer <registration_access_token>
Response 204 No Content
POST /oauth/register/{client_id}/secret — Rotate client secret
Auth: Authorization: Bearer <registration_access_token>
Response 200:
DELETE /oauth/register/{client_id}/registration-token — Rotate registration access token
Auth: Authorization: Bearer <registration_access_token>
Response 200:
Authorization Code Flow
GET /oauth/authorize — Authorization endpoint
Auth: Optional session cookie (user must be logged in to approve)
Query parameters:
| Parameter | Required | Description |
|---|---|---|
response_type | Yes | Must be code |
client_id | Yes | Registered client ID |
redirect_uri | Yes | Must match registered redirect URIs |
scope | Yes | Space-separated scopes (e.g. openid profile email) |
state | Recommended | CSRF protection value |
code_challenge | Yes (PKCE) | Base64url-encoded SHA-256 of verifier |
code_challenge_method | Yes (PKCE) | Must be S256 |
Response: Redirects to consent page or redirect_uri with code=...&state=....
Error: Redirects to redirect_uri with error=access_denied&error_description=....
POST /oauth/authorize — Submit consent decision
Auth: Optional session cookie
Body (application/x-www-form-urlencoded): Consent form fields set by the hosted consent page.
Response: Redirects to redirect_uri?code=<auth-code>&state=<state>.
Token Endpoint
POST /oauth/token — Issue tokens (all grants)
Auth: Client credentials via Authorization: Basic base64(client_id:client_secret) or client_id/client_secret in body.
Content-Type: application/x-www-form-urlencoded
Grant: authorization_code
Request:
Response 200:
Grant: refresh_token
Grant: client_credentials
Response 200:
Grant: urn:ietf:params:oauth:grant-type:token-exchange (RFC 8693)
Used by agents to delegate on behalf of a user or to narrow scope.
Response 200: Same shape as client_credentials response. The resulting token carries the user subject and agent delegation chain in the act claim.
DPoP-bound tokens (RFC 9449)
Include a DPoP proof header on the token request:
The issued access token will contain a cnf.jkt claim (public key thumbprint). Subsequent resource requests must include a fresh DPoP proof matching the key.
Error 400:
Token Revocation
POST /oauth/revoke — Revoke a token (RFC 7009)
Auth: Client credentials
Request (application/x-www-form-urlencoded):
token=<access-or-refresh-token>&token_type_hint=access_token
Response 200: Empty body. Always returns 200 even if token was already revoked or unknown (per RFC 7009 §2.2).
Token Introspection
POST /oauth/introspect — Introspect a token (RFC 7662)
Auth: Client credentials
Request (application/x-www-form-urlencoded):
token=<access-token>&token_type_hint=access_token
Response 200 — active token:
Response 200 — revoked/expired token:
Notable behavior: Revoked tokens return
active: false— the response body never reveals why (revoked vs. expired) to avoid information leakage.
UserInfo
GET /oauth/userinfo — UserInfo endpoint (OIDC Core §5.3)
Auth: Authorization: Bearer <access-token> with openid scope
Response 200:
JWKS
GET /.well-known/jwks.json — JSON Web Key Set (RFC 7517)
Auth: None (public)
Response 200 (Cache-Control: public, max-age=300):
Returns active and recently-retired signing keys (within 2× access token TTL window) so in-flight tokens remain verifiable during key rotation.
Discovery
GET /.well-known/oauth-authorization-server — RFC 8414 Authorization Server Metadata
Auth: None (public)
Response 200:
Device Authorization
POST /oauth/device — Device Authorization Request (RFC 8628)
Auth: Client credentials
Response 200:
GET /oauth/device/verify — Display verification page (RFC 8628)
Auth: Optional session cookie
POST /oauth/device/verify — Submit device approval (RFC 8628)
Auth: Optional session cookie
Note on device flow in v0.1: The device authorization grant endpoints are registered and functional. However, the default scope policy and consent UI for headless flows are experimental. Monitor
GET /api/v1/admin/oauth/device-codesto triage pending device flows from the admin dashboard.