OpenNIT-Vault-Extension/docs/ARCHITECTURE.md
Claude 32cc4de8be
Vorschlaege weichen Seiten-Comboboxen, 2FA-Code bereitlegen
Vorschlagsliste: Bisher galt jedes E-Mail-Feld als Anmeldefeld
(isUsernameField gibt bei type=email bedingungslos true zurueck), und das
Dropdown liegt mit maximalem z-index direkt unter dem Feld. Auf Seiten
mit eigener Auswahlliste - etwa einem Benutzer-Picker - verdeckte es
deren Treffer, die dadurch nicht mehr anklickbar waren.

Zwei Regeln davor: Felder mit eigener Vorschlagsliste (ARIA-Combobox mit
aria-autocomplete/aria-controls/aria-expanded oder <input list>) bekommen
keine Vault-Vorschlaege mehr, sofern autocomplete sie nicht ausdruecklich
als Anmeldefeld ausweist. Und sobald der Nutzer selbst tippt, blendet
sich die Liste aus und bleibt es, bis das Feld wieder leer ist.

2FA-Code bereitlegen: Nach dem Ausfuellen eines Eintrags mit 2FA bleibt
dieser fuenf Minuten vorgemerkt. Taucht danach ein 2FA-Feld auf oder wird
es fokussiert - auch auf einer Folgeseite -, wird ein frischer Code
geholt und in die Zwischenablage gelegt, statt wie bisher nur einmal zum
Fuellzeitpunkt (wo er bis zum 2FA-Schritt laengst rotiert waere).
Automatisch wird ausschliesslich kopiert; ins Feld geschrieben wird ein
Code weiterhin nur bei ausdruecklicher Auswahl. Geschrieben wird zuerst
ueber die Seite und, falls diese keinen Zugriff bekommt, ueber das
Offscreen-Dokument des Hintergrunds. Abschaltbar in den Einstellungen.

Beim Sperren des Tresors werden Vormerkung und ausstehender Fuellauftrag
verworfen. Der Seiten-Scan des MutationObservers laeuft jetzt gedrosselt
statt bei jeder einzelnen Mutation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G12DRMpe4UjYDwuRU1sjy1
2026-07-31 13:05:30 +00:00

5.5 KiB
Raw Blame History

Architektur

Überblick

Die Erweiterung ist ein Manifest-V3-Client ohne eigenen Server. Sie besteht aus vier Kontexten, die über chrome.runtime-Nachrichten kommunizieren:

┌───────────────┐   Messages    ┌──────────────────────┐   HTTPS/Bearer   ┌──────────────────┐
│  popup.html   │ ───────────▶  │  background.js       │ ───────────────▶ │  OpenNIT-Server  │
│  popup.js     │ ◀───────────  │  (Service Worker)    │ ◀─────────────── │  /api/vault/...  │
└───────────────┘               │  - Cache (5 Min)     │                  └──────────────────┘
┌───────────────┐   Messages    │  - Lock-Gate         │
│  content.js   │ ───────────▶  │  - Favicon-Cache     │
│ (jede Seite)  │ ◀───────────  │  - Clipboard-Timer   │
└───────────────┘               └──────────┬───────────┘
                                           │ CLIP_WRITE
                                  ┌────────▼─────────┐
                                  │  offscreen.html  │  (Zwischenablage leeren)
                                  └──────────────────┘

Komponenten

Datei Rolle
background.js Zentrale Logik: API-Aufrufe, 5-Minuten-Cache, Lock-Gate, Favicon-Cache (Data-URLs), Zwischenablage-Timer. Alle Secrets fließen hier durch.
content.js Wird auf jeder Seite ausgeführt. Erkennt Benutzer-/Passwort-/OTP-Felder (inkl. Shadow-DOM, mehrstufige Logins, segmentierte OTP-Felder), zeigt das Vorschlags-Dropdown und füllt Felder framework-kompatibel (React/Vue/Angular).
popup.html / popup.js Toolbar-Popup: Liste, Suche, Detailansicht, Anlegen + Generator, PIN-Schirm.
options.html / options.js Einstellungen: Server-URL, SSO-Anmeldung, PIN-Sperrdauer, Zwischenablage.
offscreen.html / offscreen.js Minimaldokument, das ausschließlich die Zwischenablage beschreibt bzw. leert (MV3-konform).

Nachrichten (Auszug)

Typ Von → Nach Zweck
CHECK_STATUS popup/content → bg Token prüfen, App-Name/User, pin_enabled
GET_LOCK / DO_UNLOCK / LOCK_NOW popup → bg PIN-Sperre abfragen/entsperren/sperren
GET_ENTRIES / GET_MATCHING_ENTRIES popup/content → bg Einträge (alle / passend zur URL)
GET_PASSWORD / GET_TOTP popup/content → bg Secret on demand
CREATE_ENTRY popup → bg Neuen Eintrag anlegen
GET_FAVICON popup/content → bg Favicon als Data-URL (serverseitig gecacht)
VAULT_FILL popup → content Aktives Tab-Formular ausfüllen
SCHEDULE_CLIP_CLEAR popup/content → bg Zwischenablage-Leerung planen
CLIP_WRITE content → bg In die Zwischenablage schreiben, wenn die Seite selbst keinen Zugriff bekommt

Server-API (in OpenNIT)

Alle Endpunkte unter /api/vault/extension/ mit Authorization: Bearer <token>:

  • GET /entries Liste (Titel, Benutzer, URL, Notizen, has_totp, favicon_domain, has_favicon)
  • GET /entries/{id}/password Passwort (protokolliert im Audit-Log)
  • GET /entries/{id}/totp aktueller TOTP-Code + Restsekunden
  • GET /entries/{id}/favicon?fetch=1 gecachtes Favicon (bei Bedarf serverseitig geholt)
  • POST /entries neuen Eintrag anlegen
  • GET /status Token gültig? + pin_enabled / pin_lock_secs
  • POST /unlock Tresor-PIN verifizieren + serverseitiges Entsperr-Fenster für den Token setzen
  • POST /lock Token sofort wieder sperren (Entsperr-Fenster zurücksetzen)
  • GET /oauth/authorize · POST /oauth/authorize SSO-Anmeldung/Zustimmung (Session, PKCE)
  • POST /oauth/token Authorization-Code- bzw. Refresh-Grant (öffentlich, PKCE) → Access/Refresh
  • POST /oauth/revoke Refresh-Kette widerrufen (Logout)

Details zum SSO-Flow: SSO-PLAN.md. Die Erweiterung nutzt SSO über chrome.identity; Access-Tokens werden im Hintergrund still per Refresh (mit Rotation) erneuert.

Lock-Gate (serverseitig erzwungen)

Ist für den Nutzer ein Tresor-PIN aktiv, liefern die Server-Endpunkte für Einträge/Passwort/TOTP erst nach frischer PIN-Entsperrung Daten (unlocked_until pro Token) und antworten sonst mit HTTP 423. Der Client spiegelt den Zustand nur (PIN-Schirm) die eigentliche Durchsetzung liegt im Server, damit ein gestohlener Token allein wertlos ist. Der Client hält seinen Entsperr-Status zusätzlich in chrome.storage.session (verfällt beim Schließen des Browsers). Die Einstellung „PIN-Sperre" legt nur die Fensterdauer fest; „Bis der Browser geschlossen wird" nutzt ein langes Serverfenster + Client-Sitzungsende.

Sicherheitsprinzipien

  • Kein Remote-Code alle Skripte im Paket (MV3-CSP-konform, keine Inline-Skripte).
  • Secrets on demand Passwörter/TOTP erst bei Nutzung, nie in der Liste.
  • Kein persistentes Secret nur URL, Sitzungstoken, Einstellungen in chrome.storage.
  • Server-seitige Krypto Ver-/Entschlüsselung im OpenNIT-Server, nicht im Browser.