From 8108dc42541332443bf7a7c3d924d59e4edfc7d8 Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 24 Sep 2026 21:16:10 -0700 Subject: [PATCH] docs(authentik): document the self-serve user-settings flow + password stage The default-user-settings-flow was missing a PasswordStage, so users could edit name/email/locale but not their password. Added a PasswordStage (InbuiltBackend) bound at order 101. Documented the flow's stage table and the two ORM gotchas (MTI through model, required backends array). --- .../Infrastructure/Authentik.md | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/serverAppConfigs-docs/Infrastructure/Authentik.md b/serverAppConfigs-docs/Infrastructure/Authentik.md index ea01dda..d67a377 100644 --- a/serverAppConfigs-docs/Infrastructure/Authentik.md +++ b/serverAppConfigs-docs/Infrastructure/Authentik.md @@ -272,6 +272,34 @@ Two secrets live in the host `.env` (git-ignored; placeholders in `dankclaw/authentik/quadlet/`, run `./scripts/deploy.sh dankclaw`. Authentik migrates the schema on startup. +## Self-serve user-settings flow (password change) + +Users change their own account details through the `default-user-settings-flow` +(`https://auth.franksdank.cloud/if/flow/default-user-settings-flow/`) — the +target of the homepage footer's "account" link. It is a `stage_configuration` +designated flow, so it renders every bound `ConfigurableStage` for the logged-in +user. + +Stages, in execution order (the `FlowStageBinding.order` field, not the M2M +insertion order): + +| order | stage | type | what it does | +|---|---|---|---| +| 20 | `default-user-settings` | `PromptStage` | intro prompt | +| 100 | `default-user-settings-write` | `UserWriteStage` | edit name / email / locale | +| 101 | `default-user-settings-password` | `PasswordStage` | change password (`InbuiltBackend`) | + +**The `PasswordStage` was missing until 2026-09-25.** The stock flow only +carried the prompt + `UserWriteStage`, so users could edit name/email/locale +but had no way to change their password. The fix: create a `PasswordStage` +(backend `authentik.core.auth.InbuiltBackend`) and bind it to the flow. Two +ORM gotchas: `Flow.stages.add()` fails on this through model +(`Can't bulk create a multi-table inherited model` — `FlowStageBinding` is +MTI), so create the `FlowStageBinding` row directly with an explicit `order`; +and `PasswordStage` requires the `backends` array (a bare `name` insert hits a +`NOT NULL` violation). Verified via the `FlowPlanner` — the plan now lists all +three stages. + ## Outpost claim cache (`proxysession`) — 403 after a group add The embedded outpost does not re-evaluate group membership per request. Each