diff --git a/README.md b/README.md
index 814157f..925d1c0 100644
--- a/README.md
+++ b/README.md
@@ -49,9 +49,12 @@ Add-on-Einstellungen öffnen und ausfüllen:
- **Verbindung testen** → lädt die Aktenschränke (Bestätigung, dass Login & URL passen)
- optional **Standard-Aktenschrank** und Default-Optionen (eml/pdf/Anhänge)
-> ⚠️ Das Passwort wird unverschlüsselt in `storage.local` gespeichert (v1). Für den
-> Produktiveinsatz sollte auf den DocuWare Identity Service / OAuth umgestellt werden
-> (`lib/auth.js` ist dafür gekapselt).
+> 🔒 **Das Passwort wird nicht gespeichert.** Es wird beim ersten Ablegen pro
+> Thunderbird-Sitzung einmal abgefragt, daraus ein OAuth-Token geholt und sofort
+> verworfen. Nur der Token bleibt im Speicher des Hintergrundskripts (überlebt keinen
+> Neustart). In `storage.local` liegen ausschließlich Server, Organisation, Benutzer
+> und Standardwerte – keine Zugangsdaten. Auch der Einstellungs-Export enthält **kein**
+> Passwort.
## Benutzung
@@ -78,7 +81,7 @@ Das Add-on wird **nicht** öffentlich auf addons.thunderbird.net gelistet, sonde
Gitea verteilt + aktualisiert.
> Im XPI und in `updates.json` stehen **keine** Zugangsdaten. Das DocuWare-Passwort
-> liegt ausschließlich lokal in `storage.local` und wird nie mitverteilt.
+> wird ohnehin nirgends gespeichert (nur Sitzungs-Token im Speicher) und nie mitverteilt.
**Einmalige Einrichtung:**
@@ -102,7 +105,9 @@ neueste dort gelistete Version.
## Bekannte Grenzen / nächste Schritte
- **PDF** ist v1 ein einfaches Text-PDF (Kopf + Klartext-Body) ohne HTML-Layout/Bilder.
-- **Auth** nur Cookie-Logon; OAuth/Identity Service noch nicht implementiert.
+- **Auth**: primär DocuWare Identity Service (OAuth, ROPC mit öffentlichem Client),
+ Fallback Cookie-Logon für alte On-Prem-Server. Passwort wird nicht gespeichert
+ (Token nur im RAM, 1× Abfrage pro Sitzung).
- **Upload-Multipart-Format** ggf. je nach DocuWare-Version anpassen
(`docuware.js → uploadDocument`).
- Mehrfachauswahl von Mails: aktuell wird die erste markierte Mail abgelegt.
diff --git a/background/background.js b/background/background.js
index c1cbeaa..8a6a6e3 100644
--- a/background/background.js
+++ b/background/background.js
@@ -1,7 +1,43 @@
// Hintergrund-Skript: Button + Kontextmenü, öffnet den Ablage-Dialog.
+// Zusätzlich Auth-Broker: hält den OAuth-Token nur im Speicher dieser TB-Sitzung
+// (siehe auth.js). Das Passwort wird einmalig zum Login durchgereicht, daraus ein
+// Token geholt und sofort verworfen – es wird NIE gespeichert.
const DIALOG_URL = "dialog/dialog.html";
+// Auth-Broker: Dialog-/Optionsfenster fragen hier den Sitzungs-Token an bzw.
+// melden sich mit dem Passwort an. So muss das Passwort nur 1x pro Sitzung getippt
+// werden und liegt nirgends auf der Platte.
+browser.runtime.onMessage.addListener((msg) => {
+ if (!msg || !msg.type) return undefined;
+
+ if (msg.type === "auth:status") {
+ return Promise.resolve({ hasToken: Auth.hasValidToken(), token: Auth.currentToken() });
+ }
+
+ if (msg.type === "auth:logon") {
+ return (async () => {
+ try {
+ const settings = await Settings.get();
+ if (!settings.serverUrl) throw new Error("Keine DocuWare-Server-URL konfiguriert.");
+ Auth.reset();
+ const r = await Auth.logon({ ...settings, password: msg.password || "" });
+ // Passwort wird hier verworfen – nur der Token bleibt im Speicher.
+ return { ok: true, mode: r.mode, token: Auth.currentToken() };
+ } catch (e) {
+ return { ok: false, error: String((e && e.message) || e) };
+ }
+ })();
+ }
+
+ if (msg.type === "auth:logout") {
+ Auth.reset();
+ return Promise.resolve({ ok: true });
+ }
+
+ return undefined;
+});
+
function openDialog(messageIds) {
const ids = Array.isArray(messageIds) ? messageIds : [messageIds];
// Pro Nachricht ein eigenes Ablagefenster (leicht versetzt gestapelt).
diff --git a/dialog/dialog.css b/dialog/dialog.css
index d569aa7..59840d4 100644
--- a/dialog/dialog.css
+++ b/dialog/dialog.css
@@ -62,3 +62,23 @@ footer { border-top: 1px solid #e5e7eb; padding: 10px 18px; background: #fafafa;
.muted { color: #6b7280; font-size: 12px; }
.err { color: #b91c1c; } .ok { color: #15803d; }
.field.invalid input, .field.invalid textarea, .field.invalid select { border-color: #b91c1c; }
+
+/* Passwort-Abfrage (Sitzungs-Login, nicht gespeichert) */
+.overlay {
+ position: fixed; inset: 0; background: rgba(0, 0, 0, .35);
+ display: flex; align-items: center; justify-content: center; z-index: 50;
+}
+.overlay[hidden] { display: none; }
+.overlay-box {
+ background: #fff; border-radius: 6px; padding: 18px 20px; width: 340px;
+ box-shadow: 0 8px 30px rgba(0, 0, 0, .25);
+}
+.overlay-box h2 { font-size: 15px; font-weight: 600; margin: 0 0 8px; }
+.overlay-box input[type="password"] {
+ width: 100%; padding: 7px 9px; border: 1px solid #b9c0c8; border-radius: 3px;
+ font: inherit; margin-top: 8px;
+}
+.overlay-box input[type="password"]:focus { outline: none; border-color: #2563eb; box-shadow: 0 0 0 2px #2563eb33; }
+.overlay-box .err { min-height: 1em; margin-top: 6px; }
+.overlay-actions { display: flex; justify-content: flex-end; align-items: center; gap: 12px; margin-top: 10px; }
+.overlay-box .pw-note { margin-top: 10px; }
diff --git a/dialog/dialog.html b/dialog/dialog.html
index 1763d5f..b8a29de 100644
--- a/dialog/dialog.html
+++ b/dialog/dialog.html
@@ -33,6 +33,21 @@
+
+
+
+
DocuWare-Anmeldung
+
+
+
+
+
+
+
+
Wird nur für diese Sitzung verwendet und nicht gespeichert.
+
+
+