# Anmeldung über authentik (OIDC) Laufzettel spricht generisches OpenID Connect mit Discovery. Der Anbieter muss also nur einen `/.well-known/openid-configuration`-Endpunkt anbieten — authentik tut das. Ein anderer Anbieter (Keycloak, Entra ID, Zitadel) funktioniert genauso, nur heißen die Menüs anders. ## 1. Provider in authentik anlegen **Anwendungen → Provider → Erstellen → OAuth2/OpenID Provider** | Feld | Wert | |---|---| | Name | `Laufzettel` | | Authorization flow | `default-provider-authorization-explicit-consent` (oder implicit) | | Client type | `Confidential` | | Redirect URIs | `https://laufzettel.example.de/api/auth/oidc/rueckruf` | | Signing Key | ein vorhandener Schlüssel | | Scopes | `openid`, `profile`, `email` und ein Scope, der `groups` liefert | Die Redirect-URI ist `APP_URL` plus `/api/auth/oidc/rueckruf` — exakt so, mit demselben Schema und ohne abschließenden Schrägstrich. Läuft Laufzettel hinter einem Reverse Proxy, ist `APP_URL` die **öffentliche** Adresse, nicht die interne. `Client ID` und `Client Secret` notieren. ## 2. Gruppen in den Token bringen Laufzettel liest die Rolle aus dem Claim `groups`. In authentik gibt es dafür den mitgelieferten Scope-Mapping `authentik default OAuth Mapping: OpenID 'profile'` nicht — du brauchst ein eigenes Mapping: **Anpassung → Property Mappings → Erstellen → Scope Mapping** - Name: `Laufzettel Gruppen` - Scope name: `groups` - Expression: ```python return { "groups": [gruppe.name for gruppe in request.user.ak_groups.all()], } ``` Dieses Mapping beim Provider unter **Advanced protocol settings → Scopes** auswählen. ## 3. Anwendung anlegen **Anwendungen → Anwendungen → Erstellen**, den Provider zuordnen, Slug z. B. `laufzettel`. Über die Anwendung steuerst du per Policy, wer sich überhaupt anmelden darf. ## 4. Gruppen für die Rollen Lege in authentik vier Gruppen an und trage die Mitglieder ein: | Gruppe | Rolle in Laufzettel | Darf | |---|---|---| | `lz-admin` | `ADMIN` | alles, inkl. Benutzer, Verzeichnis, Abteilungen, Archiv-Verwaltung | | `lz-redakteur` | `REDAKTEUR` | Vorlagen anlegen, bearbeiten, veröffentlichen | | `lz-techniker` | `TECHNIKER` | Läufe starten, abarbeiten, abschließen, archivieren; Geräte pflegen | | `lz-leser` | `LESER` | nur lesen | Ist jemand in mehreren Gruppen, gewinnt die stärkere Rolle. ## 5. Laufzettel konfigurieren In der `.env`: ```dotenv APP_URL=https://laufzettel.example.de OIDC_ISSUER=https://authentik.example.de/application/o/laufzettel/ OIDC_CLIENT_ID=... OIDC_CLIENT_SECRET=... OIDC_NAME=authentik OIDC_GROUP_ADMIN=lz-admin OIDC_GROUP_EDITOR=lz-redakteur OIDC_GROUP_TECHNICIAN=lz-techniker OIDC_GROUP_VIEWER=lz-leser ``` Den `OIDC_ISSUER` zeigt authentik beim Provider unter **OpenID Configuration Issuer** an. Der abschließende Schrägstrich gehört dazu. Danach neu starten: ```bash docker compose up -d ``` ## 6. Was beim Login passiert - Ein unbekannter Benutzer wird beim ersten Login **angelegt** (JIT-Provisioning) - Die Rolle wird bei **jedem** Login aus `groups` neu gesetzt — eine Änderung in authentik greift ab der nächsten Anmeldung - Ist der Benutzer in keiner der vier Gruppen, bekommt er `LESER` - Wer vor dem Login eine bestimmte Seite aufgerufen hat (z. B. `/t/LZ-7K3F9Q` nach dem Scannen eines QR-Codes), landet danach genau dort ## 7. Notfallzugang Fällt authentik aus, kommt niemand mehr in Laufzettel. Für diesen Fall gibt es den lokalen Login: ```dotenv AUTH_LOCAL_ENABLED=true ``` Er ist standardmäßig **aus**. Ein lokales Admin-Konto legst du über den Seed an (`SEED_ADMIN_EMAIL`, `SEED_ADMIN_PASSWORD`) oder als Admin unter **Admin → Benutzer**. Die Passwörter liegen als argon2-Hash in der Datenbank. Empfehlung: ein einziges lokales Admin-Konto, Passwort im Passwortmanager, `AUTH_LOCAL_ENABLED` im Normalbetrieb auf `false` und nur im Notfall umgestellt. ## 8. Fehlersuche | Symptom | Ursache | |---|---| | `redirect_uri_mismatch` | Die URI in authentik stimmt nicht zeichengenau mit `APP_URL` + `/api/auth/oidc/rueckruf` überein — oft `http` gegen `https` oder ein abschließender Schrägstrich | | Nach dem Login wieder auf der Anmeldeseite | Das Cookie ist `Secure`, die Verbindung aber `http`. Entweder HTTPS nutzen oder zum Testen über `localhost` gehen | | Jeder bekommt `LESER` | Der Claim `groups` fehlt im Token. Scope-Mapping aus Schritt 2 angelegt und beim Provider ausgewählt? | | Discovery schlägt fehl | `OIDC_ISSUER` falsch oder von der App aus nicht erreichbar. Im Compose-Stand hängt `web` im Netz `extern` — prüfen, ob der Name auflösbar ist |