First Upload

This commit is contained in:
friloo 2026-07-01 18:26:57 +02:00 committed by GitHub
parent efc6fcbafa
commit c61677d47f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 3921 additions and 0 deletions

78
docs/ARCHITECTURE.md Normal file
View file

@ -0,0 +1,78 @@
# 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, Token, PIN-Sperrdauer, Zwischenablage. |
| `offscreen.html` / `offscreen.js` | Minimaldokument, das ausschließlich die Zwischenablage 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** |
| `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 |
## 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`](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, Token, Einstellungen in `chrome.storage`.
- **Server-seitige Krypto** Ver-/Entschlüsselung im OpenNIT-Server, nicht im Browser.