Skip to content

feat(auth): register Tribelt as an OIDC client - #75

Merged
ExtraToast merged 2 commits into
mainfrom
feat/tribelt-oidc-client
Sep 30, 2026
Merged

ExtraToast merged 2 commits into
mainfrom
feat/tribelt-oidc-client

Conversation

@ExtraToast

Copy link
Copy Markdown
Contributor

What

Registers tribelt as a confidential OIDC client that also requires PKCE, for the student test site at tribelt.jorisjonkers.dev and its /stats dashboard.

  • New ServicePermission.TRIBELT("tribelt").
  • buildTribeltClient(): authorization_code + refresh_token, client_secret_basic/post, PKCE required, no consent, default token settings, scopes openid profile email, redirect https://tribelt.jorisjonkers.dev/auth/callback, post-logout redirect https://tribelt.jorisjonkers.dev/ (plus the .test variants every downstream client carries).
  • "tribelt" to ServicePermission.TRIBELT in DOWNSTREAM_CLIENT_PERMISSIONS.

Why this shape

The public site is anonymous, so there is no forward-auth in front of it. The grant is enforced at the authorize endpoint instead, the same way Outline (NOTES) works: only admins and users holding TRIBELT get a code. The ID token already carries roles with SERVICE_TRIBELT / ROLE_ADMIN, which the app double-checks. Userinfo does not include roles.

No migration: user_service_permissions.service is a VARCHAR(50) without a check constraint, as with NOTES, HERMES and OVERLEAF.

Deploy prerequisites

  • Vault key auth.clients.tribelt.secret in secret/data/auth-api (written before the fleet-infra change lands).
  • fleet-infra adds the AUTH_CLIENTS_TRIBELT_SECRET template line; until then the @Value default applies and the client is unusable in production.

Verification

  • :api:test :api:ktlintCheck :api:detekt: 206/206, clean.
  • :api:integrationTest (OAuth2Flow, ForwardAuth, SecurityFilterChainRouting, Testcontainers): 76/76.

The Tribelt mirror at tribelt.jorisjonkers.dev signs its /stats viewers in
against this authorization server. Adds the registered client, a TRIBELT
service permission, and the client_id -> permission mapping that gates the
authorize endpoint -- the Outline/NOTES shape.

The client is confidential (client_secret_basic and client_secret_post)
and also requires PKCE. Redirect is /auth/callback, post-logout redirect
is the site root; .test variants mirror every other downstream client.
The secret comes from auth.clients.tribelt.secret, defaulting to
tribelt-secret for local runs and tests exactly like the other clients.

TRIBELT is enforced here rather than by forward-auth: the public site
route is anonymous, so a forward-auth middleware would never run.
DOWNSTREAM_CLIENT_PERMISSIONS moves the check to the authorize endpoint;
ADMIN passes as usual.

The ID token already carries a roles claim (ROLE_<role> plus
SERVICE_<permission> per grant, every SERVICE_* for ADMIN), so the app
can double-check SERVICE_TRIBELT after the gate. Userinfo uses the
default mapper and returns only standard scope claims, not roles.

No migration: user_service_permissions.service is VARCHAR(50) with no
check constraint, and the OpenAPI spec does not enumerate permissions.
@ExtraToast ExtraToast added type: feature New user-facing or operator-facing capability. area: auth Authentication, authorization, sessions, or identity. labels Sep 30, 2026
Adding the tribelt secret pushed AuthorizationServerConfig's constructor
past detekt's LongParameterList limit of six.
@ExtraToast
ExtraToast merged commit ef45d3d into main Sep 30, 2026
9 checks passed
@ExtraToast
ExtraToast deleted the feat/tribelt-oidc-client branch September 30, 2026 16:53
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.

1 participant