Skip to content

API Authentication

Sergio Soto edited this page Mar 25, 2026 · 1 revision

API Authentication

SpaceHarbor supports four authentication strategies. The active strategy depends on environment configuration.

Canonical Paths

Resource Path
API Base /api/v1/
Swagger UI /api/docs
OpenAPI Spec /openapi.json

Security Schemes

Scheme Type Header / Method Use Case
BearerAuth HTTP Bearer (JWT) Authorization: Bearer <jwt> User sessions (web UI, CLI, integrations)
ApiKeyAuth API Key x-api-key: <key> Service-to-service, media worker automation
ServiceTokenAuth API Key x-service-token: <token> Internal machine-to-machine communication
ScimTokenAuth HTTP Bearer Authorization: Bearer <scim-token> Identity provider SCIM 2.0 provisioning

All four schemes are defined in the OpenAPI spec at /openapi.json under components.securitySchemes.

IAM Modes

Mode Config Behavior
Disabled (default dev) SPACEHARBOR_IAM_ENABLED unset or false Legacy auth: write ops may require x-api-key if SPACEHARBOR_API_KEY is set
Shadow SPACEHARBOR_IAM_ENABLED=true + SPACEHARBOR_IAM_SHADOW_MODE=true Full auth required; RBAC decisions logged but not enforced. Dev-only.
Enforced (production) SPACEHARBOR_IAM_ENABLED=true + SPACEHARBOR_IAM_SHADOW_MODE=false Full auth + RBAC enforcement. Required for production.

Public Endpoints (Auth Bypass)

These endpoints bypass authentication even when IAM is fully enabled:

Endpoint Purpose
GET /health Liveness probe
GET /health/ready Readiness probe
POST /auth/login User login
POST /auth/refresh Token refresh
GET /auth/token Token refresh (GET variant)
GET /events/stream SSE event stream
POST /device/code Device authorization grant
POST /device/token Device token exchange
GET /openapi.json OpenAPI spec
GET /api/docs/* Swagger UI

Login Flow (JWT)

1. Authenticate

curl -X POST http://localhost:8080/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email": "admin@spaceharbor.dev", "password": "Admin1234!dev"}'

Response:

{
  "accessToken": "eyJhbGciOiJIUzI1NiI...",
  "refreshToken": "a1b2c3d4e5f6...",
  "expiresIn": 3600,
  "mustChangePassword": false
}

2. Use the Access Token

curl http://localhost:8080/api/v1/assets \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiI..."

3. Refresh When Expired

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

The old refresh token is revoked upon use (rotation).

4. Revoke a Session

curl -X POST http://localhost:8080/api/v1/auth/revoke \
  -H "Authorization: Bearer <accessToken>" \
  -H "Content-Type: application/json" \
  -d '{"refreshToken": "a1b2c3d4e5f6..."}'

API Key Authentication

For service-to-service integrations (media workers, CI/CD pipelines):

curl -X POST http://localhost:8080/api/v1/assets/ingest \
  -H "x-api-key: sh_your-secret-key" \
  -H "Content-Type: application/json" \
  -d '{"title": "Automated Ingest", "sourceUri": "s3://bucket/clip.mov"}'

Configure API keys:

SPACEHARBOR_API_KEY=sh_your-secret-key           # Single key
SPACEHARBOR_API_KEYS=sh_key1,sh_key2,sh_key3     # Multiple keys (rotation)

Users can also create personal API keys via the API:

POST /api/v1/api-keys    # Create key (returns plaintext once)
GET  /api/v1/api-keys    # List keys (hashed)
DELETE /api/v1/api-keys/:id  # Revoke key

SCIM Token Authentication

For identity provider provisioning (Okta, Azure AD, etc.):

curl http://localhost:8080/scim/v2/Users \
  -H "Authorization: Bearer <scim-token>"

Configure: SPACEHARBOR_SCIM_TOKEN=<secure-token>

Bootstrap (First-Time Setup)

On a fresh deployment with no users:

curl -X POST http://localhost:8080/api/v1/auth/bootstrap \
  -H "Content-Type: application/json" \
  -d '{
    "email": "admin@company.com",
    "displayName": "System Admin",
    "password": "SecurePassword123!"
  }'

This creates the initial super_admin user. The endpoint returns 410 Gone after first use.

In development mode (NODE_ENV=development), a default admin is created automatically:

  • Email: admin@spaceharbor.dev
  • Password: Admin1234!dev

Role Hierarchy

Role Level Scope Description
viewer 1 Project Read-only access
artist 2 Project Upload, submit for review
lead 3 Project Approve/reject, manage shots
production 4 Project Manage project members, delivery
supervisor 5 Project Full project control
administrator 6 Global User management, settings
super_admin 7 Global Everything, including role transfer

CSRF Protection

State-changing requests from browser sessions require a CSRF token:

X-CSRF-Token: <token-from-login-response>

The CSRF hook is active for all non-GET requests when credentials are cookie-based.

TLS Enforcement

In production (non-development), TLS is enforced by default via X-Forwarded-Proto:

  • Requests without https receive 421 HTTPS Required
  • Localhost connections are exempted
  • Override: SPACEHARBOR_REQUIRE_TLS=false

See Also

Clone this wiki locally