Skip to content

feat(auth): register the estate dashboard as an OIDC client - #84

Merged
ExtraToast merged 1 commit into
mainfrom
feat/79-estate-dashboard-oidc-client
Oct 2, 2026
Merged

ExtraToast merged 1 commit into
mainfrom
feat/79-estate-dashboard-oidc-client

Conversation

@ExtraToast

Copy link
Copy Markdown
Contributor

What

Registers estate-dashboard as a confidential OIDC client that also requires PKCE, for the estate delivery dashboard at estate.jorisjonkers.dev (JorisJonkers-dev/estate-dashboard).

  • buildEstateDashboardClient(): authorization_code + refresh_token, client_secret_basic/post, PKCE required, no consent, default token settings, scopes openid profile email, redirect https://estate.jorisjonkers.dev/auth/callback, post-logout redirect https://estate.jorisjonkers.dev/ (plus the .test variants every downstream client carries).
  • DownstreamClientSecrets.estateDashboard, from auth.clients.estate-dashboard.secret.

Closes #79. Part of JorisJonkers-dev/deploy-kit#195.

Why this shape

The dashboard is admin-only, but the client is deliberately not in DOWNSTREAM_CLIENT_PERMISSIONS. JorisJonkers-dev/estate-dashboard#2 has the dashboard read ROLE_ADMIN from the ID token's roles claim and show a non-admin its own Not-an-admin page; a 403 from the authorize endpoint would pre-empt that page. So every signed-in user gets a code, and refusing non-admins rests on the dashboard's own check. There is no new ServicePermission, and no migration.

The ID token already carries roles with ROLE_ADMIN for admins, and the customizer re-reads the user on refresh, so a renewed token keeps it and a demoted admin loses it at the next renewal.

Deploy prerequisites

  • Vault key auth.clients.estate-dashboard.secret in secret/data/auth-api (written before the fleet-infra change lands).
  • fleet-infra adds AUTH_CLIENTS_ESTATE_DASHBOARD_SECRET to the auth-api template. The dash-dropping AUTH_CLIENTS_ESTATEDASHBOARD_SECRET does not resolve the @Value placeholder; checked against a system-environment property source. Until then the @Value default applies and the client is unusable in production.

Verification

  • :api:test :api:ktlintCheck :api:detekt: 209/209, clean.
  • :api:integrationTest (Testcontainers): 250/250.
  • The two new integration tests run the real flow and reach a code: an admin sees ROLE_ADMIN in the ID token and again after a refresh-token grant; a non-admin gets a code and no ROLE_ADMIN. Removing the client's registration turns both red.
  • They send the authorize parameters in the query string. The older downstream-client tests pass them through MockMvc param(), get 400 OAuth 2.0 Parameter: response_type, and return early, so they never reach a code. Fixing those is Make the downstream OIDC flow tests reach an authorization code #83.

Adds `estate-dashboard`, the tribelt shape: a confidential client
(client_secret_basic and client_secret_post) that also requires PKCE,
authorization_code plus refresh_token, scopes openid profile email, no
consent. Redirect https://estate.jorisjonkers.dev/auth/callback and
post-logout redirect to the site root, with the .test variants.

The secret comes from auth.clients.estate-dashboard.secret, supplied as
AUTH_CLIENTS_ESTATE_DASHBOARD_SECRET. The dash-dropping
AUTH_CLIENTS_ESTATEDASHBOARD_SECRET form does not resolve the @value
placeholder; checked against a system-environment property source.

The client is deliberately absent from DOWNSTREAM_CLIENT_PERMISSIONS.
The dashboard reads ROLE_ADMIN from the roles claim itself and shows
a non-admin its own Not-an-admin page, which a 403 from the authorize
endpoint would pre-empt.

The integration tests run the real flow and reach a code: authorize
parameters go in the query string, because the authorization server
reads a GET authorization request from the query string alone. The
older downstream-client tests pass them through MockMvc param(), get
400 "OAuth 2.0 Parameter: response_type", and return early. An admin
sees ROLE_ADMIN in the ID token, and again after a refresh; a non-admin
gets a code and no ROLE_ADMIN.

Closes #79
@ExtraToast ExtraToast added type: feature New user-facing or operator-facing capability. area: auth Authentication, authorization, sessions, or identity. labels Oct 2, 2026
@ExtraToast
ExtraToast merged commit 2f03ab7 into main Oct 2, 2026
10 checks passed
@ExtraToast
ExtraToast deleted the feat/79-estate-dashboard-oidc-client branch October 2, 2026 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: auth Authentication, authorization, sessions, or identity. type: feature New user-facing or operator-facing capability.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Register the estate dashboard as an OIDC client

1 participant