Skip to content

Authentication & Permissions ​

Bonsai Backend uses two authentication mechanisms: JWT tokens for operator REST API access, and API keys for WebSocket conversation sessions.

Operator Authentication (JWT) ​

Login ​

Operators authenticate by posting credentials to the login endpoint:

bash
curl -X POST http://localhost:3000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{ "id": "operator", "password": "your-password" }'

The response includes an access token and a refresh token:

json
{
  "accessToken": "eyJhbG...",
  "refreshToken": "eyJhbG...",
  "operatorId": "operator",
  "roles": ["super_admin"]
}

Using Tokens ​

Include the access token in the Authorization header:

Authorization: Bearer eyJhbG...

Refreshing Tokens ​

When the access token expires, use the refresh token to obtain a new pair:

bash
curl -X POST http://localhost:3000/api/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{ "refreshToken": "eyJhbG..." }'

Role-Based Access Control (RBAC) ​

Operators are assigned one or more roles. Each role carries a set of permissions in entity:action format.

Roles ​

RoleDescription
super_adminFull system access — all permissions
content_managerManage content entities: projects, agents, stages, classifiers, transformers, tools, knowledge, providers, API keys
supportView projects and conversations, manage users and issues
developerRead-only access to most entities plus system configuration
viewerRead-only access to most entities

Permissions ​

Permissions follow the entity:action pattern:

EntityReadWriteDelete
Operatoroperator:readoperator:writeoperator:delete
Useruser:readuser:writeuser:delete
Projectproject:readproject:writeproject:delete
Agentagent:readagent:writeagent:delete
Stagestage:readstage:writestage:delete
Classifierclassifier:readclassifier:writeclassifier:delete
Context Transformercontext_transformer:readcontext_transformer:writecontext_transformer:delete
Tooltool:readtool:writetool:delete
Global Actionglobal_action:readglobal_action:writeglobal_action:delete
Guardrailguardrail:readguardrail:writeguardrail:delete
Knowledgeknowledge:readknowledge:writeknowledge:delete
Conversationconversation:readconversation:writeconversation:delete
Issueissue:readissue:writeissue:delete
Providerprovider:readprovider:writeprovider:delete
API Keyapi_key:readapi_key:writeapi_key:delete
Environmentenvironment:readenvironment:writeenvironment:delete
Migrationmigration:exportmigration:import—
Systemsystem:config——
Auditaudit:read——
Analyticsanalytics:read——

Defense in Depth ​

Security is enforced at two layers:

  1. Controller layer — checkPermissions() validates the request before processing
  2. Service layer — requirePermission() ensures security even when services are called internally

API Keys ​

API keys provide authentication for WebSocket conversation sessions. They are scoped to a project and used by client applications (web apps, mobile apps, kiosks).

Creating an API Key ​

bash
curl -X POST http://localhost:3000/api/projects/my-project/api-keys \
  -H "Authorization: Bearer eyJhbG..." \
  -H "Content-Type: application/json" \
  -d '{ "name": "Production Web App" }'

The response includes the full key — this is the only time it's shown:

json
{
  "id": "key-uuid",
  "name": "Production Web App",
  "key": "bonsai_abcdef123456...",
  "keyPreview": "bonsai_abc...456",
  "isActive": true
}

Using API Keys ​

API keys are used exclusively for WebSocket authentication. The client sends the key in the auth message after connecting:

json
{
  "type": "auth",
  "apiKey": "bonsai_abcdef123456..."
}

Managing API Keys ​

  • List — GET /api/projects/:projectId/api-keys
  • Deactivate — Update isActive to false to disable without deleting
  • Delete — DELETE /api/projects/:projectId/api-keys/:id

Deactivated keys are immediately rejected on WebSocket authentication attempts.

Initial Setup ​

When the system has no operator accounts, the setup endpoint is available:

bash
POST /api/setup/initial-operator

This creates the first super operator account. The endpoint is disabled after the first operator is created.

Audit Logs ​

All write operations are recorded in the audit log with:

  • Who performed the action (userId)
  • What action was taken (action)
  • Which entity was affected (entityId, entityType)
  • Previous state (oldEntity) and new state (newEntity)
  • Timestamp

Audit logs are read-only and accessible to users with the audit:read permission.

Released under the Apache-2.0 License.