storage-service

Authentication (JWKS)

storage-service does not issue tokens. It verifies Bearer JWTs created by identity-service.

Configure the identity URL

Set this in .env (or your orchestrator / Coolify / Compose env). IDENTITY_JWKS_URL is the main knob — switch between local and production without code changes.

# Local identity-service
IDENTITY_JWKS_URL=http://localhost:8000/.well-known/jwks.json

# Hosted identity
IDENTITY_JWKS_URL=https://id.shellui.com/.well-known/jwks.json

Shorthand (JWKS path appended automatically):

IDENTITY_SERVICE_URL=https://id.shellui.com
# → https://id.shellui.com/.well-known/jwks.json

If both are set, IDENTITY_JWKS_URL wins. If neither is set, the default is http://localhost:8000/.well-known/jwks.json.

Docker Compose passes IDENTITY_JWKS_URL from .env (default inside Compose: http://host.docker.internal:8000/.well-known/jwks.json so the container can reach identity on the host).

The home page and GET /storage/v1/health show the resolved JWKS URL so you can confirm what the process is using.

Configuration reference

Variable Purpose
IDENTITY_JWKS_URL Full JWKS document URL (preferred)
IDENTITY_SERVICE_URL Identity base URL; JWKS path is derived if IDENTITY_JWKS_URL is empty
IDENTITY_ISSUER Optional iss claim check
IDENTITY_AUDIENCE Optional aud claim check
JWKS_CACHE_TTL Seconds to cache JWKS (default 900)
JWT_HS256_FALLBACK_SECRET Dev-only: verify HS256 when JWKS has no keys (identity DEBUG=true). Rejected at startup if DEBUG=false unless ALLOW_JWT_HS256_FALLBACK=true
ALLOW_JWT_HS256_FALLBACK Explicit escape hatch to allow HS256 fallback when DEBUG=false (not recommended in production)
JWT_ALGORITHMS Default RS256

Expected claims

Claim Use
sub / user_id Owner id for uploads and per-user quotas
company_id Tenancy — buckets and objects are scoped to this company
email Informational
user_metadata.is_staff Quota admin APIs
user_metadata.is_company_owner Quota admin for own company

Client headers

Authorization: Bearer <access_token>

Optional Supabase-style apikey header is accepted by CORS but ignored for authorization.

WebDAV

Third-party WebDAV clients may send: