Skip to content

API Tokens

scarecr0w12 edited this page Jun 24, 2026 · 1 revision

API Tokens

API tokens provide persistent, revocable authentication for programmatic access to CortexPrism. Tokens are SHA-256 hashed before storage, support team-scoping, expiration dates, and last-used tracking.

Token Format

Tokens follow the format cortex_token_<uuid> and are returned in plaintext only at creation time. The stored value is a SHA-256 hash — tokens cannot be recovered after creation.

cortex_token_550e8400-e29b-41d4-a716-446655440000

Creating Tokens

REST API

POST /api/auth/tokens
Content-Type: application/json

{
  "name": "My CI Token",
  "teamIds": ["team_abc123"],
  "expiresDays": 90
}

Parameters:

Field Required Description
name Yes Human-readable name for the token
teamIds No Array of team IDs to scope the token to
expiresDays No Number of days until expiration (null = never expires)

Response (201):

{
  "id": "tok_550e8400-...",
  "token": "cortex_token_550e8400-...",
  "name": "My CI Token"
}

The token field is the only time the plaintext token is returned.

CLI

cortex login --token cortex_token_550e8400-e29b-41d4-a716-446655440000

This saves the token to ~/.cortex/auth.json for persistent CLI authentication. You can also specify the server host:

cortex login --token <token> --host http://my-cortex:3000

Using Tokens

Include tokens in the Authorization header of API requests:

curl -H "Authorization: Bearer cortex_token_..." http://localhost:3000/api/agents

The extractIdentity() function in src/server/auth.ts parses the Bearer token, validates it against the user_tokens table, and constructs a RequestIdentity with the user's ID, team memberships, and admin status.

Listing Tokens

GET /api/auth/tokens
Authorization: Bearer cortex_token_...

Returns all non-revoked tokens for the authenticated user:

[
  {
    "id": "tok_abc123",
    "name": "My CI Token",
    "team_ids": "[\"team_xyz\"]",
    "created_at": "2026-06-24T00:00:00Z",
    "expires_at": "2026-09-22T00:00:00Z",
    "last_used_at": "2026-06-24T12:00:00Z",
    "revoked_at": null
  }
]

Revoking Tokens

DELETE /api/auth/tokens/:id
Authorization: Bearer cortex_token_...

Revokes the specified token by setting revoked_at in the user_tokens table. Only the token owner can revoke their own tokens.

Response:

{ "ok": true }

Team-Scoping

Tokens can be scoped to specific teams via the teamIds parameter. When a token is team-scoped, the RequestIdentity only includes the specified team IDs (rather than all teams the user belongs to). This limits what the token can access:

  • Agents scoped to teams outside the token's scope are invisible
  • Team management endpoints require membership in the scoped team

If teamIds is omitted or empty, the token inherits all of the user's team memberships.

Expiration

Tokens can optionally expire after a configurable number of days. Expired tokens are rejected during validation — validateApiToken() checks expires_at against the current time.

// Validation logic in src/server/auth.ts
if (row.expires_at && row.expires_at < new Date().toISOString()) return null;

Tokens without an expiration date (expires_at = NULL) never expire.

Last-Used Tracking

Each time a token is validated, the last_used_at column is updated:

UPDATE user_tokens SET last_used_at = datetime('now') WHERE token_hash = ?

This provides an audit trail of which tokens are actively in use.

Storage Security

Property Detail
Hash algorithm SHA-256
Salt None (native token format provides sufficient entropy via UUID)
Storage user_tokens table in cortex.db
Plaintext visibility Only at creation time; never logged or stored

The user_tokens table schema:

CREATE TABLE user_tokens (
  id TEXT PRIMARY KEY,
  user_id TEXT NOT NULL REFERENCES users(id),
  name TEXT NOT NULL,
  token_hash TEXT NOT NULL,
  team_ids TEXT DEFAULT '[]',
  created_at TEXT NOT NULL,
  expires_at TEXT,
  last_used_at TEXT,
  revoked_at TEXT
);

Database Table

Column Type Description
id TEXT tok_<uuid> — token identifier
user_id TEXT FK to users.id
name TEXT Human-readable label
token_hash TEXT SHA-256 hash of the plaintext token
team_ids TEXT JSON array of scoped team IDs
created_at TEXT ISO 8601 creation timestamp
expires_at TEXT ISO 8601 expiration (null = never)
last_used_at TEXT ISO 8601 last validation timestamp
revoked_at TEXT ISO 8601 revocation timestamp (null = active)

Node Tokens

Node tokens use a similar prefix (cortex_node_) and are validated through a separate pathway in validateApiToken(). When a valid node token is presented, the identity is set to { type: 'instance' } — granting instance-level access for swarm and distributed node operations.

See Also

Clone this wiki locally