56 lines
3.5 KiB
Markdown
56 lines
3.5 KiB
Markdown
|
|
# Anmeldung und Bücher-Schlüssel
|
||
|
|
|
||
|
|
## Zwei Wege hinein
|
||
|
|
|
||
|
|
**Benutzername und Passwort** (`accounts/views.py` `login_view`): Das Login-Formular leitet im
|
||
|
|
Browser aus dem Passwort den Bücher-Schlüssel ab (PBKDF2-SHA256, Salt `diora:<username>`,
|
||
|
|
200 000 Runden) und legt ihn bis zur nächsten Seite in `localStorage['diora_pending_enc_key']`
|
||
|
|
ab. Die App-Seite übernimmt ihn als `diora_enc_key_<userId>` (`32-crypto.js`, `99-init.js`).
|
||
|
|
|
||
|
|
**Authelia (OpenID Connect)** (`accounts/oidc.py`, `accounts/oidc_views.py`): als zusätzlicher
|
||
|
|
Weg, die Anmeldung mit Passwort bleibt. Der Ablauf ist Authorization Code mit PKCE (S256) und
|
||
|
|
einem vertraulichen Client (`client_secret_basic`). Das id_token wird hier geprüft (RS256 gegen
|
||
|
|
die JWKS des Anbieters, `iss`, `aud`, `exp`, `nonce`), dafür reicht `cryptography`.
|
||
|
|
|
||
|
|
- Ein Konto wird **einmal verknüpft**: in den Einstellungen „Mit Authelia verknüpfen“, während
|
||
|
|
man normal angemeldet ist (`/accounts/oidc/start/?link=1`). Gespeichert wird `OidcIdentity`
|
||
|
|
(`issuer`, `sub`; Name und Mail nur zur Anzeige). Danach führt „Mit Authelia anmelden“ auf der
|
||
|
|
Login-Seite in dieses Konto.
|
||
|
|
- Eine nicht verknüpfte Authelia-Identität wird abgewiesen. Es entstehen **keine neuen
|
||
|
|
Konten** über Authelia, und es wird auch nicht über Name oder Mail automatisch verknüpft.
|
||
|
|
- Wer hinein darf, regelt Authelia (Policy `mitglieder` = Gruppen `admins` oder `freunde`).
|
||
|
|
- Einstellungen per Umgebung: `DIORA_OIDC_ISSUER`, `DIORA_OIDC_CLIENT_ID`,
|
||
|
|
`DIORA_OIDC_CLIENT_SECRET`, `DIORA_OIDC_REDIRECT_URI` (fest, weil hinter dem Proxy kein
|
||
|
|
https erkannt wird), optional `DIORA_OIDC_PROVIDER_NAME`. Fehlt eins der ersten drei, gibt es
|
||
|
|
keinen Knopf. Auf prod stehen sie in `~/docker-compose/diora-prod/.env` (Strato), das
|
||
|
|
Gegenstück liegt auf Hetzner in `/opt/authelia/oidc-clients.env`.
|
||
|
|
- Redirect-URI im Authelia-Client: `https://diora.creamfresh.xyz/accounts/oidc/callback/`.
|
||
|
|
|
||
|
|
## Der Schlüssel nach einer Authelia-Anmeldung
|
||
|
|
|
||
|
|
Ohne Passwort gibt es keinen Schlüssel. Deshalb erzeugt `getOrCreateEncKey()` **nie mehr
|
||
|
|
selbst einen neuen Schlüssel**: Früher machte es einen zufälligen, wenn keiner da war, und damit
|
||
|
|
waren die vorhandenen Bücher auf diesem Gerät verloren. Jetzt fragt es `dioraUnlock()`
|
||
|
|
(`static/js/app/33-unlock.js`). Es gibt zwei Wege:
|
||
|
|
|
||
|
|
1. **Von einem entsperrten Gerät übergeben** (`accounts/keyshare.py`, Modell `KeyShare`). Das
|
||
|
|
neue Gerät schickt einen ECDH-P-256-Public-Key und zeigt einen 6-stelligen Code, der aus
|
||
|
|
diesem Key berechnet wird. Entsperrte Geräte fragen alle 15 s
|
||
|
|
`/accounts/keyshare/pending/` ab und zeigen denselben Code mit „Freigeben/Ablehnen“. Die
|
||
|
|
Freigabe verschlüsselt den Bücher-Schlüssel mit AES-GCM unter dem gemeinsamen Geheimnis
|
||
|
|
(HKDF-SHA256, info `diora keyshare v1`). Der Server sieht nur Public Keys und Chiffrat und
|
||
|
|
gibt die Antwort genau einmal heraus. Anträge laufen nach 10 min ab. Angeboten werden nur
|
||
|
|
solche, deren Gerät in den letzten 20 s nachgefragt hat, und je Konto höchstens 5, die
|
||
|
|
ältesten weichen.
|
||
|
|
2. **Das diora-Passwort einmal eingeben**: dieselbe Ableitung wie beim Login.
|
||
|
|
|
||
|
|
In beiden Fällen wird der Schlüssel an einem Buch geprüft, bevor er gespeichert wird. Mit
|
||
|
|
„Später“ bleiben Bücher gesperrt, und die Bibliothek zeigt einen Knopf „Entsperren“. Die
|
||
|
|
Einstellungsseite erzeugt ebenfalls keinen Schlüssel mehr.
|
||
|
|
|
||
|
|
## Apps
|
||
|
|
|
||
|
|
Android und Desktop melden sich bisher nur mit Passwort an (eigene Login-Seiten in
|
||
|
|
`diora-android/web-native/login.html` und `diora-desktop/src/web/login.js`, die einen
|
||
|
|
API-Token holen). Authelia für die Apps folgt als eigener Schritt.
|