raw .md

Authentication

The token endpoint

POST /api/v1/token

The body may be JSON or form-encoded. grant_type defaults to password when it is omitted.

grant_typerequired fieldsresult
password (client)username, passwordclient token, scope client
password (app user)client_id, client_secret, username, passwordapp user token, scope app profile
client_credentialsclient_id, client_secretapp token, scope app, no user
authorization_codecode, client_id, client_secret, redirect_uriapp user token

client_id in a token request is the app's app_key, not the client's cid.

Client password grant

curl -sS -X POST "$API/token" \
  -H "Content-Type: application/json" \
  -d '{"grant_type":"password","username":"acme","password":"..."}'

The response has scope client and a cid.

App user password grant

curl -sS -X POST "$API/token" \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "password",
    "client_id": "app_1a2b3c4d5e6f7a8b",
    "client_secret": "gsk_...",
    "username": "alice",
    "password": "..."
  }'

The app must be active and the app secret must match. When sub-apps are used, app users are shared across the app family.

Client credentials grant

curl -sS -X POST "$API/token" \
  -H "Content-Type: application/json" \
  -d '{"grant_type":"client_credentials","client_id":"app_...","client_secret":"gsk_..."}'

This returns an app token with scope app and no user. Use it for server to server calls that act as the app itself.

Authorization code grant

See OAuth flow.

Token response

{
  "access_token": "cgt_...",
  "certified_gump_token": "cgt_...",
  "token_type": "Bearer",
  "expires_in": 43200,
  "scope": "app profile",
  "issued_at": 1761200000,
  "sub": "a_9k2m4x",
  "uid": "a_9k2m4x",
  "app": "app_1a2b3c4d5e6f7a8b",
  "app_username": "alice",
  "client": "c_4m2x9p"
}

access_token and certified_gump_token are the same value. expires_in is authoritative. There is no refresh token.

Sending a token

curl -sS "$API/userinfo" -H "Authorization: Bearer cgt_..."

The public API also accepts X-Gauth-Token: cgt_....

A gak_ app user key can be sent as a bearer token directly. It has no expiry and is revoked individually.

Identity

GET /api/v1/userinfo and GET /api/v1/me are aliases.

{
  "active": true,
  "sub": "a_9k2m4x",
  "uid": "a_9k2m4x",
  "app_username": "alice",
  "email": "alice@example.com",
  "display_name": "Alice",
  "status": "active",
  "app": "app_1a2b3c4d5e6f7a8b",
  "app_name": "acme-app",
  "client": "c_4m2x9p",
  "scope": "app profile",
  "expires_at": 1761243200,
  "expires_in": 43199,
  "token_kind": "api"
}

A client token returns cid instead of uid and app.

Client self-service

These require a client token.

curl -sS -X PATCH "$API/me" -H "Authorization: Bearer $CGT" \
  -H "Content-Type: application/json" \
  -d '{"email":"new@example.com","display_name":"New Name"}'

curl -sS -X POST "$API/me/password" -H "Authorization: Bearer $CGT" \
  -H "Content-Type: application/json" \
  -d '{"current_password":"old","new_password":"a-long-password"}'

curl -sS -X POST "$API/me/delete-request" -H "Authorization: Bearer $CGT" \
  -H "Content-Type: application/json" \
  -d '{"reason":"closing the project"}'

Changing a client password revokes every other session for that client.

App user self-service

curl -sS -X POST "$API/apps/app_1a2b3c4d5e6f7a8b/password" \
  -H "Authorization: Bearer $CGT" \
  -H "Content-Type: application/json" \
  -d '{"current_password":"old","new_password":"a-long-password"}'

My keys

curl -sS "$API/me/keys" -H "Authorization: Bearer $CGT"

curl -sS -X POST "$API/me/keys" -H "Authorization: Bearer $CGT" \
  -H "Content-Type: application/json" -d '{"label":"laptop"}'

curl -sS -X DELETE "$API/me/keys/7" -H "Authorization: Bearer $CGT"

The raw key is returned once, at creation. Afterwards only the hint is visible.

Introspection

POST /api/v1/introspect requires client authentication: a client API key or client_id plus client_secret.

curl -sS -X POST "$API/introspect" \
  -H "Content-Type: application/json" \
  -d '{"token":"cgt_...","client_id":"app_...","client_secret":"gsk_..."}'

An unknown, expired or revoked token returns {"active": false}.

Revocation

POST /api/v1/revoke always returns 200, even for an unknown token.

curl -sS -X POST "$API/revoke" \
  -H "Content-Type: application/json" -d '{"token":"cgt_..."}'

Health

GET /api/v1/health is unauthenticated.

{"status":"ok","service":"gauth","issuer":"https://auth.gumpworks.com"}