Auth & Security
Olly uses Keycloak as its OpenID Connect provider. This page covers the identity and authorization model. For PHI handling, consent, erasure, and audit, see Data Protection.
Implemented vs designed
The identity model below (realm, clients, grants, JWT validation) is what runs today. The fine-grained authorization mesh (OPA/ABAC, service-mesh mTLS, PHI audit logging, multi-realm isolation) is draft design (see Designs → Access Control), not running. Sections are labelled accordingly.
Identity (implemented)
There is one realm, olly, on Keycloak at auth.dev.hiolly.com (container olly-keycloak, port 8093). Keycloak is fronted by nginx; APISIX (:9080) is the API gateway for the Go services. The access-token TTL is 15 minutes.
| Client | Grant | App | JWT claim |
|---|---|---|---|
web-employer | PKCE (auth code) | employer SPA (Vite + React PWA) | org_locator |
web-member | ROPC (password) | member SPA (Vite + React) | party_locator |
web-admin | direct grant / OIDC | admin console (Next.js) | |
web-provider | public | provider portal | |
mobile-app | direct grant | mobile |
Not every flow is PKCE: the employer SPA uses PKCE, but the member and mobile clients use ROPC / direct grant (which is what makes the copy-paste token in the API Quickstart possible). Service-to-service calls use the client-credentials grant against the same token endpoint.
Auth flow per app (implemented)
- Employer SPA: PKCE Authorization Code; the JWT carries
org_locatorto scope the request to one scheme. - Member SPA: ROPC: the app exchanges username/password for a token carrying
party_locator. - Admin console (Next.js): Keycloak OIDC.
- Mobile: direct grant.
- Service-to-service: client credentials (e.g. the seeder gets an admin token this way).
The JWT's org_locator (employer) or party_locator (member) is the scoping claim every downstream check keys on.
JWT validation (implemented; finer authz is designed)
APISIX validates the bearer token (signature against the Keycloak JWKS, issuer, expiry) and forwards to the Go service, which re-validates as defence in depth (JWKS cached in-process). Beyond that coarse check, the fine-grained authorization layer is designed, not built: the OPA/ABAC policy checks, the per-resource member_id-matches checks, and service-mesh mTLS in the diagram below are roadmap items in Designs → Access Control, not running in the dev stack (which is Docker Compose on Hetzner with no service mesh).
Roles (intended model)
Roles live in the olly realm as Keycloak realm roles. The table is the intended model; enforcement today is coarse (gateway + claim scoping), with attribute-based enforcement (a member sees only their own resources, a provider only their patients) being the designed OPA/ABAC layer.
| Role | Summary |
|---|---|
MEMBER | View/submit own claims, view coverage and EOBs, manage own enrollment |
EMPLOYER_ADMIN | MEMBER scope for their group, manage group enrollment, billing overview |
PROVIDER | View claims for their patients, submit claims, view prior auth and credentialing |
CLAIMS_ADJUSTER | Read/adjudicate claims, decide prior auths, view member PHI (to be audit-logged) |
UNDERWRITER | Actuarial data, rate tables, read-only claims aggregates |
NETWORK_MANAGER | Provider credentialing, network contracts, directory |
SYSTEM_ADMIN | Realm administration, policy and secret management |
Sessions (implemented)
Keycloak issues 15-minute access tokens with refresh-token rotation (each refresh issues a new token and invalidates the prior one; reuse of a stolen refresh token invalidates the session family). Re-authentication is forced on password change and at hard session expiry.
Designed, not yet built
These are in Designs → Access Control at draft status, with no running implementation:
- Multi-realm isolation: separate realms per user population (members / providers / internal / services). Today it is the single
ollyrealm. - OPA / ABAC: attribute-based authorization at the gateway and in-service (the per-resource and PHI-field checks).
- Service-mesh mTLS and
/internal/*mesh-only enforcement. - OpenBao-driven secret rotation for M2M client secrets.
- PHI access logging and 6-year WORM audit retention: the CloudTrail/S3 Object Lock and OpenSearch-ILM retention described in older drafts targets an AWS/managed deployment; it is not running. See Data Protection for the real audit posture (consent-scoped only today).
