Kaiten
Authentication

Service Accounts & Tokens

Create machine users and API tokens for programmatic access.

Service Accounts & Tokens

Service Accounts are machine users that access the Kaiten API programmatically using API Tokens (ksh_*).

Creating a Service Account

Via Console

  1. Navigate to Integrations → Service Accounts
  2. Click New Service Account
  3. Enter a name (e.g. "CI/CD Pipeline")
  4. The service account is created within your organization
Service Accounts list

Via API

curl -X POST http://localhost:6000/api/service-accounts \
  -H "Authorization: Bearer <your-jwt>" \
  -H "Content-Type: application/json" \
  -d '{"name": "CI/CD Pipeline"}'

Generating a Token

Each service account can have multiple tokens with different scopes:

curl -X POST http://localhost:6000/api/service-accounts/<sa-id>/tokens \
  -H "Authorization: Bearer <your-jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "production",
    "scopes": ["read:customers", "write:instances", "read:feature_flags"]
  }'

Response:

{
  "id": "uuid-...",
  "name": "production",
  "token": "ksh_abcdef123456...",
  "scopes": ["read:customers", "write:instances", "read:feature_flags"]
}

Important: Copy the token immediately — it is shown only once and stored hashed.

Using the Token

Include the token in the Authorization header:

curl http://localhost:6000/api/customers \
  -H "Authorization: Bearer ksh_abcdef123456..."

How ForwardAuth Works

  1. Traefik detects the ksh_ prefix in the Authorization header
  2. Request is forwarded to /api/tokens/validate (ForwardAuth)
  3. The API validates the token hash and checks expiry
  4. An unsigned JWT is generated with: UserID, OrganizationID, and Scopes
  5. This JWT is forwarded to the API handler via Traefik headers
  6. The handler extracts the Principal and scopes all queries accordingly

Token Security

PropertyDetail
Formatksh_ prefix + random bytes
StorageSHA-256 hashed in database
ExpiryOptional, set at creation
RevocationDelete the token via API or dashboard
ScopesEnforced per endpoint by the API handler

On this page