feat(backend): derive LEITUNGSTEAM from the Authentik groups claim
On every Authentik login the token's `groups` claim is compared against AUTHENTIK_LEITUNGSTEAM_GROUP (default "Leitungsteam") and mirrored to the new User.isLeitungsteam column. LT is global, not KC-scoped, so it lives on the User rather than as a per-KC Membership row: toAuthenticatedUser() synthesises a virtual global LEITUNGSTEAM membership from the flag, so RolesGuard / visibility / TeamerService keep working unchanged. - provision helper gains an isLeitungsteam arg and reconciles the flag both ways (grant on join, drop when the group is gone), capturing a User UPDATE to the sync log. - verifyAuthentikClaims() now also returns isLeitungsteam; strategy, WS path and onboarding all funnel through the shared helper + mapper. - new env var AUTHENTIK_LEITUNGSTEAM_GROUP. Tests: provision-user.spec.ts extended (flag up/down, virtual membership); npm test green at 55. Docs updated; ops note added that the Authentik provider must emit the groups claim. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+14
-12
@@ -7,7 +7,7 @@ architecture context).
|
||||
|
||||
```bash
|
||||
npm install
|
||||
cp .env.example .env # then fill in DATABASE_URL / AUTHENTIK_ISSUER_URL / GUEST_JWT_SECRET / TEAM_JWT_SECRET
|
||||
cp .env.example .env # DATABASE_URL / AUTHENTIK_ISSUER_URL / AUTHENTIK_LEITUNGSTEAM_GROUP / GUEST_JWT_SECRET / TEAM_JWT_SECRET
|
||||
npx prisma generate
|
||||
npx prisma migrate dev --name init # requires a running PostgreSQL instance
|
||||
npm run start:dev
|
||||
@@ -24,12 +24,14 @@ client's host - no separate web server is needed.
|
||||
"Konfi-Castle-ID"); this API acts as an OIDC **resource server**, verifying
|
||||
access tokens against Authentik's JWKS (`AuthentikStrategy`). The local
|
||||
`User` is provisioned just-in-time on first login from the token claims
|
||||
(`resolveOrProvisionAuthentikUser`); role + KC/Gemeinde scope then come
|
||||
from local `Membership` rows (only `status = ACTIVE` ones count). A freshly
|
||||
provisioned user has no membership and thus no rights until one is granted
|
||||
(LT: manually for now; Verantwortliche: the `onboarding/` approval flow).
|
||||
Clients perform the Authorization Code + PKCE flow against Authentik
|
||||
directly.
|
||||
(`resolveOrProvisionAuthentikUser`), and `User.isLeitungsteam` is
|
||||
reconciled on every login from the token's `groups` claim vs.
|
||||
`AUTHENTIK_LEITUNGSTEAM_GROUP` — `toAuthenticatedUser` then synthesises a
|
||||
virtual global `LEITUNGSTEAM` membership from that flag. Other roles come
|
||||
from local `Membership` rows (only `status = ACTIVE` ones count).
|
||||
Verantwortliche self-provision through the `onboarding/` approval flow;
|
||||
a user with neither the LT flag nor a membership has no rights. Clients
|
||||
perform the Authorization Code + PKCE flow against Authentik directly.
|
||||
- Gemeinde Teamer are **local accounts** (no Authentik): a `User` row with a
|
||||
`passwordHash` and `kcId` set, `authentikSub` left null. A Gemeinde
|
||||
Verantwortliche/r creates them directly or via a `TeamerInvite`
|
||||
@@ -110,8 +112,8 @@ client's host - no separate web server is needed.
|
||||
|
||||
All planned backend phases are implemented. `npm test` runs Jest unit tests
|
||||
(`ZuteilungService`, `TeamAuthService`, `TeamerService`, `OnboardingService`,
|
||||
`resolveOrProvisionAuthentikUser`; Prisma mocked). Remaining work: the
|
||||
Flutter clients (see repo root README), deriving the LT `Membership` from
|
||||
Authentik group claims (the `User` is provisioned, the role is not), invite
|
||||
email delivery, and the first real Prisma migration (only `schema.prisma`
|
||||
exists so far).
|
||||
`resolveOrProvisionAuthentikUser` / `toAuthenticatedUser`; Prisma mocked).
|
||||
Remaining work: the Flutter clients (see repo root README), invite email
|
||||
delivery, push notifications, and the first real Prisma migration (only
|
||||
`schema.prisma` exists so far). Ops note: the Authentik provider must emit a
|
||||
`groups` claim in the access token for the LT check to work.
|
||||
|
||||
Reference in New Issue
Block a user