Groundfloor Docs

Authentication

Keycloak JWT authentication for Control Plane customer and workspace-scoped API calls.

All customer API endpoints require a Bearer JWT issued by the platform Keycloak realm.

Request header

Authorization: Bearer <access_token>
Content-Type: application/json
export CP_URL="https://dev-platform.groundfloor.cloud"
export TOKEN="<keycloak_access_token>"

curl -s -H "Authorization: Bearer $TOKEN" \
  "$CP_URL/v1/workspaces" | jq .

Token claims

ClaimUsage
subStable user ID — mapped to Portal users row
emailDisplay and membership lookup
issMust match platform realm issuer (KEYCLOAK_ISSUER)

Control Plane resolves sub → internal user ID, then checks SpiceDB for the requested action on the target resource.

Permission model

Authorization is ReBAC, not role strings alone. Common actions:

read · write · delete · ddl · administer · manage_members · view_billing · deploy

A 403 means SpiceDB denied the action — not an invalid token.

Workspace-scoped endpoints

Routes under /v1/workspaces/{workspace_id}/… require:

  1. Valid JWT
  2. read / write / delete / ddl on that workspace (per endpoint)

Public endpoints

Unauthenticated, rate-limited:

EndpointPurpose
GET /v1/public/tls-authorizeACME TLS authorization
GET /v1/public/routeEdge hostname → upstream routing
GET /v1/public/workspaces/{id}/apps/by-slugShell bootstrap

See Front Door and Shell bootstrap.

Local development

VariableCustomer PortalControl Plane API
Keycloak URLNEXT_PUBLIC_KEYCLOAK_URLKEYCLOAK_ISSUER
API URLNEXT_PUBLIC_API_URLhttp://localhost:8088

Obtain a token by signing in to the Customer Portal locally, or use Keycloak direct grant in dev.

Errors

StatusMeaning
401Missing, malformed, or expired JWT
403Valid JWT but SpiceDB denied the action