Skip to content

docs(auth): verify open/SMART auth end to end + local Keycloak (#198)#207

Open
angela-helios wants to merge 2 commits into
mainfrom
docs/198-auth-verification
Open

docs(auth): verify open/SMART auth end to end + local Keycloak (#198)#207
angela-helios wants to merge 2 commits into
mainfrom
docs/198-auth-verification

Conversation

@angela-helios

Copy link
Copy Markdown
Contributor

Deliverable for #198. Everything in the verification section was executed against a running stack (HFS + Keycloak 26.1 from docker/keycloak/), not read off the code.

docs/auth-verification.md covers

  1. Auth verified end to end — a results table (14 checks): SMART discovery served + auth-exempt, 401 with no token, SMART v2 scope enforcement (full-access writes; read-only client gets 403 on create and on an out-of-scope type), signature/tampering, algorithm allow-list, issuer, JWKS fetch, JTI (all three backends), and audience (positive + negative).
  2. Local Keycloak runbook — bring-up, token retrieval, running HFS against the realm, accept/deny.
  3. UI login flow — the intended browser Authorization Code + PKCE flow (sequence diagram) and exactly what HFS must add (authorize/callback routes, server-side state + PKCE verifier, session cookie, discovery wiring, a public realm client). Design for a follow-up, not built here.
  4. Login-screen theming matrix — Keycloak / Okta / Auth0 / Entra: what each can customize and how portable it is, with a recommendation (do IdP-native theming; ship a Helios Keycloak theme; document branding knobs for the others; keep HFS out of the login-screen business).

Defects found while verifying (filed separately)

Neither is fixed here — this pass verifies and reports.

Low-risk fixes included (so the runbook works as written)

  • docker/keycloak/realm.json: hardcoded-audience mapper (aud: hfs-api) on both service clients, so audience validation is exercisable locally — verified matching aud200, wrong expected aud401. (Makes auth: HFS_AUTH_AUDIENCE is not enforced when the token lacks an aud claim #206 observable; doesn't fix the missing-claim bypass.)
  • docker/keycloak/get-token.sh: parse the token JSON with whichever of jq/node/python3 actually works (a Windows python3 stub alias resolves but fails), instead of python3 only.

Not covered (called out in the doc)

  • private_key_jwt with a real asymmetric client assertion — the committed realm's clients use client-secret; HFS's validation role is identical either way, but the advertised capability isn't exercised until the realm gains such a client.
  • Discovery advertises private_key_jwt + RS384/ES384 while the realm uses client-secret + RS256 — a config-fidelity gap (documented, not filed).

Closes #198.

Deliverable for #198: end-to-end verification of open/SMART auth against
the committed local Keycloak, the runbook, the UI login-flow design, and
an IdP login-screen theming matrix.

- docs/auth-verification.md: what was verified and how (discovery, 401,
  scope enforcement full/read-only, signature, algorithm allow-list,
  issuer, JWKS, JTI, audience), the Keycloak runbook, the browser
  Authorization Code + PKCE login-flow design and what HFS must add, and
  a login-screen customization matrix across Keycloak/Okta/Auth0/Entra
  with a recommendation.

Two defects found and filed while verifying:
- #205: the JTI replay cache rejects legitimate reuse of bearer access
  tokens (default config unusable against Keycloak; workaround
  HFS_AUTH_JTI_BACKEND=disabled).
- #206: HFS_AUTH_AUDIENCE is not enforced when the token omits aud.

Low-risk fixes included so the runbook works as written:
- docker/keycloak/realm.json: add a hardcoded-audience mapper (aud:
  hfs-api) to both service-account clients so audience validation is
  exercisable locally (verified: matching aud 200, wrong aud 401).
- docker/keycloak/get-token.sh: parse the token response with whichever
  of jq/node/python3 actually works, not python3 only (a Windows stub
  alias resolves but fails).
@claude

claude Bot commented Jul 6, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Deliver the section-4 recommendation from the auth verification: brand the
Keycloak login screen in the IdP (HFS is not the auth server).

- docker/keycloak/themes/helios/: CSS-only login theme extending the
  stock keycloak theme -- Helios logo, Figtree, accent #33b8ff, light
  surface, from the Dashboard V1.1 tokens (crates/ui/assets/app.css). No
  template forks, so it survives Keycloak upgrades. Includes the
  password show/hide input-group styling for Keycloak 26.
- docker-compose.yml: mount ./themes read-only.
- realm.json: select the theme (loginTheme: helios), rename the realm
  display to Helios FHIR Server, and add the scaffolding to render the
  browser login end to end -- a public Authorization Code + PKCE client
  (hfs-web) and a demo/demo test user. These are what the #198 section-3
  browser-login build will plug into.
- docs/auth-verification.md: recommendation and notes updated from
  recommended to shipped for the theme and interactive client.

Rendered and verified via headless Chrome against the running Keycloak.
@angela-helios

angela-helios commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

Helios login theme (part 4 of #198 — login-screen customization)

Answering the customization question concretely: yes, and here it is. Since HFS is not the auth server, the login screen is IdP-owned — so this brands Keycloak (the IdP we bundle) with a CSS-only theme: Helios logo, Figtree, accent #33b8ff, light surface, all from the Dashboard V1.1 tokens. It extends the stock keycloak theme with no template forks, so it survives Keycloak upgrades.

Wired up: docker/keycloak/themes/helios/ mounted into the container, selected via the realm loginTheme, and rendered end to end through a new public Authorization Code + PKCE client (hfs-web) + demo/demo test user — the scaffolding the §3 browser-login build will plug into.

Rendered and verified via headless Chrome against the running Keycloak. The password show/hide input-group needed extra styling for Keycloak 26 — a defect caught only because the page was actually rendered, not curl'd.
helios-login-screenshot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Auth: verify open/SMART auth end to end, configure local Keycloak, and scope out the UI login screen + IdP theming

1 participant