diff --git a/TOPICS.md b/TOPICS.md index a1b5f03..eb4ad84 100644 --- a/TOPICS.md +++ b/TOPICS.md @@ -71,6 +71,8 @@ Lade immer zuerst diese Datei. Dann gezielt die passende(n) Referenz-Datei(en). | Dev-Setup | d-guides/dev-setup.md | Lokale Umgebung starten | | Secrets-Verschluesselung | d-guides/encrypt-env-secrets.md | Env-Dateien verschluesseln | | Google OAuth | d-guides/google-oauth-setup.md | OAuth Auth/Data Apps einrichten (inkl. Calendar/Contacts-Scopes + Reconnect-Hinweis) | +| Google Portal + Env-Checkliste | d-guides/google-registration-checklist.md | GCP-Projekt, APIs, Redirects, Env-Variablen, Code-Referenzen | +| Microsoft Entra + Env-Checkliste | d-guides/microsoft-entra-registration-checklist.md | App registration, Graph delegated permissions, Redirects, Env-Variablen | | Infomaniak Token-Setup | d-guides/infomaniak-token-setup.md | Personal Access Token im Infomaniak-Manager fuer kDrive/Calendar/Contacts erzeugen | | Security-Migration | d-guides/security-migration-guide.md | JWT Cookie Migration | | Doc-Sync Cursor-Rule | d-guides/cursor-doc-sync.md | Installation, Regel-Quelle `doc-sync.mdc`, Doku-Workflow | diff --git a/c-work/_CHANGELOG.md b/c-work/_CHANGELOG.md index e1c87fb..557d5b9 100644 --- a/c-work/_CHANGELOG.md +++ b/c-work/_CHANGELOG.md @@ -14,6 +14,7 @@ Skip: reine Refactors, Formatting, Lint, Dep-Bumps, Test-only, Wiki-Tippfehler. ## 2026-05-11 +- 2026-05-11 | docs | wiki | d-guides: `google-registration-checklist.md`, `microsoft-entra-registration-checklist.md` (Vendor-Registrierung + Gateway-Env/Code-Referenzen); TOPICS ergänzt. - 2026-05-11 | feat | gateway, frontend-nyla, wiki | TeamsBot: `GET /api/teamsbot/{instanceId}/dashboard/stream` (SSE dashboardState 3s/20s); dashboard consumes EventSource + reconnect; module tiles navigate to `modules?moduleId=` with expand + scroll highlight; canonical `b-reference/teams-bot/architecture.md`, TOPICS, `b-reference/frontend-nyla/architecture.md` (Teams Bot UI row). (c-work: 2-build/2026-04-teamsbot-greenfield-ia-and-live-update.md) ## 2026-05-10 diff --git a/d-guides/deployment/poweron-sec.kdbx b/d-guides/deployment/poweron-sec.kdbx index e514c2f..68e5bae 100644 Binary files a/d-guides/deployment/poweron-sec.kdbx and b/d-guides/deployment/poweron-sec.kdbx differ diff --git a/d-guides/google-oauth-setup.md b/d-guides/google-oauth-setup.md index 051ee5b..64531b9 100644 --- a/d-guides/google-oauth-setup.md +++ b/d-guides/google-oauth-setup.md @@ -3,6 +3,8 @@ ## Overview This guide explains how to set up Google OAuth 2.0 authentication for the Porta application. +**Checkliste (Google Cloud + Gateway-Env):** [google-registration-checklist.md](google-registration-checklist.md). + ## Prerequisites - A Google account - Access to Google Cloud Console (https://console.cloud.google.com/) diff --git a/d-guides/google-registration-checklist.md b/d-guides/google-registration-checklist.md new file mode 100644 index 0000000..bd9e182 --- /dev/null +++ b/d-guides/google-registration-checklist.md @@ -0,0 +1,116 @@ +# Checkliste: Google Cloud — PORTA (OAuth + Speech) + +Operative Liste: **was im Google Cloud Projekt** (z. B. Organisation `poweron-center-ai-org`, Projekt **PowerOn Porta**) **eingerichtet** werden muss und **welche Gateway-Variablen/Code-Stellen** dazu passen. + +Detaillierte OAuth-Schritte und Troubleshooting: [`google-oauth-setup.md`](google-oauth-setup.md). + +--- + +## 1) Google Cloud Console — APIs aktivieren + +Projekt auswählen → **APIs & Services** → **Library**. + +| API | Wofür im Gateway | +|-----|------------------| +| **Gmail API** | Mail-Connector (readonly-Scope) | +| **Google Drive API** | Drive-Connector (readonly) | +| **Google Calendar API** | Kalender-Connector (readonly) | +| **People API** | Kontakte (readonly) | +| **Cloud Speech-to-Text API** | STT (`/voice-google/stt/*`) | +| **Cloud Text-to-Speech API** | TTS über `ConnectorGoogleSpeech` | + +--- + +## 2) OAuth-Zustimmungsbildschirm + +**APIs & Services** → **OAuth consent screen**. + +- App-Name, Support-Mail, Developer Contact wie von Google gefordert. +- **Scopes** müssen zur Code-Basis passen (Single Source of Truth): + +`gateway/modules/auth/oauthProviderConfig.py` → `googleAuthScopes`, `googleDataScopes` + +Kurzreferenz: + +| Zweck | Scopes | +|-------|--------| +| Nur Login (**Auth-App**) | `openid`, `userinfo.email`, `userinfo.profile` | +| Datenverbindung (**Data-App**) | wie Auth **plus** `gmail.readonly`, `drive.readonly`, `calendar.readonly`, `contacts.readonly` | + +Hinweis: Nach **Scope-Erweiterung** müssen Nutzer Google-Verbindungen in der UI **Reconnect** auslösen (siehe `google-oauth-setup.md`). + +--- + +## 3) OAuth 2.0 Client(s) — „Web application“ + +**APIs & Services** → **Credentials** → **Create credentials** → **OAuth client ID**. + +Das Gateway unterstützt **getrennte Auth- und Data-Clients** (unterschiedliche Client-IDs) oder **einen gemeinsamen Client** (in den Envs sind ID/Secret für Auth und Data oft identisch). + +**Authorized redirect URIs** — pro öffentlich erreichbare Gateway-Basis-URL **zwei** Einträge (Pfad exakt, inkl. `http`/`https`): + +| Pfad | Verwendung | +|------|------------| +| `{origin}/api/google/auth/login/callback` | Login-Flow (`Service_GOOGLE_AUTH_REDIRECT_URI`) | +| `{origin}/api/google/auth/connect/callback` | Connect/Reconnect (`Service_GOOGLE_DATA_REDIRECT_URI`) | + +**In diesem Repo typische Origins** (jeweils beide Callbacks eintragen): + +- Lokal: `http://localhost:8000` +- INT: `https://gateway-int.poweron.swiss` +- PROD: `https://gateway-prod.poweron.swiss` +- Forgejo/ALT-Prod (falls genutzt): `https://api.poweron.swiss` — in `env-gateway-prod-forgejo.env` Google `*_REDIRECT_URI` ggf. noch setzen. + +Backend-Routing: `gateway/modules/routes/routeSecurityGoogle.py`. + +--- + +## 4) Speech / Voice (ohne User-OAuth) + +**Credentials** → **API key** (empfohlen:auf Speech + TTS beschränken) **oder** Service-Account nach Vorgabe des Connector (siehe `gateway/modules/connectors/connectorVoiceGoogle.py`: `Connector_GoogleSpeech_API_KEY_SECRET` kann API-Key oder SA-JSON sein). + +Doku STT/TTS: [`b-reference/gateway/voice-google.md`](../b-reference/gateway/voice-google.md). + +--- + +## 5) Gateway — Env-Dateien anpassen + +Alle Werte **ohne** echte Secrets im Wiki; in den Deploy-Envs mit eurem Verschlüsselungsworkflow pflegen ([`encrypt-env-secrets.md`](encrypt-env-secrets.md)). + +| Variable | Bedeutung | +|----------|-----------| +| `Service_GOOGLE_AUTH_CLIENT_ID` | OAuth Client (Login) | +| `Service_GOOGLE_AUTH_CLIENT_SECRET` | Geheimnis (verschlüsselt) | +| `Service_GOOGLE_AUTH_REDIRECT_URI` | Muss **1:1** mit Google Console Login-Callback übereinstimmen | +| `Service_GOOGLE_DATA_CLIENT_ID` | OAuth Client (Connector); darf = Auth sein | +| `Service_GOOGLE_DATA_CLIENT_SECRET` | Geheimnis (verschlüsselt) | +| `Service_GOOGLE_DATA_REDIRECT_URI` | Muss **1:1** mit Google Console Connect-Callback übereinstimmen | +| `Connector_GoogleSpeech_API_KEY_SECRET` | Speech/TTS API-Key oder SA-JSON (verschlüsselt) | + +**Dateien (Stand Repo):** `gateway/env-gateway-dev.env`, `env-gateway-int.env`, `env-gateway-prod.env`, `env-gateway-prod-forgejo.env`, ggf. `gateway/.env`. + +Zusätzlich — wenn neues **Frontend** oder neuer **API-Host**: + +- `APP_API_URL` muss die Basis sein, unter der `/api/google/...` erreichbar ist (Cookie/SameSite-Kontext). +- `APP_ALLOWED_ORIGINS` — CORS für das UI, falls neue Origins dazukommen. + +--- + +## 6) Gateway — Python (nur bei Scope-/API-Änderungen) + +| Datei | Wann anfassen | +|-------|----------------| +| `gateway/modules/auth/oauthProviderConfig.py` | Neue/entfernte Google-Scopes für Login oder Datenverbindung | +| `gateway/modules/routes/routeSecurityGoogle.py` | Nur bei Flow-/Route-Änderungen (unüblich) | +| `gateway/modules/auth/tokenManager.py` | Nutzt `Service_GOOGLE_DATA_*` für Refresh — keine manuelle Anpassung bei reiner Registrierung | + +Token-Refresh und Microsoft/Google Data: `gateway/modules/auth/tokenManager.py`. + +--- + +## 7) Smoke-Tests + +- [ ] Login mit Google: redirected zu Google, Rückkehr ohne `redirect_uri_mismatch` +- [ ] **Verbindungen** → Google connect/reconnect +- [ ] Drive/Mail/Kalender/Kontakte je nach Feature smoke-testen +- [ ] STT/TTS: kurzer Aufruf über Voice-Route (siehe `voice-google.md`) diff --git a/d-guides/microsoft-entra-registration-checklist.md b/d-guides/microsoft-entra-registration-checklist.md new file mode 100644 index 0000000..0f5b263 --- /dev/null +++ b/d-guides/microsoft-entra-registration-checklist.md @@ -0,0 +1,113 @@ +# Checkliste: Microsoft Entra ID — PORTA (OAuth) + +Operative Liste: **was in der App-Registrierung** im Ziel-Tenant (z. B. **poweron.swiss**) **konfiguriert** werden muss und **welche Gateway-Variablen/Code-Stellen** dazu passen. + +Hintergrund Konzept Auth- vs. Data-App: [`z-archive/concepts/OAuth-Auth-vs-Data-Connection-Konzept.md`](../z-archive/concepts/OAuth-Auth-vs-Data-Connection-Konzept.md). + +**Hinweis:** App-Registrierungen lassen sich nicht „in einen anderen Tenant verschieben“. Neu im Ziel-Tenant anlegen (oder bewusst Multi-Tenant), Secrets neu erzeugen, Nutzer müssen sich ggf. neu anmelden / Microsoft-Verbindungen neu verbinden. + +--- + +## 1) Entra Admin Center — App registration + +[Azure Portal](https://portal.azure.com) → **Microsoft Entra ID** → **App registrations** → **New registration**. + +- **Name:** z. B. PowerOn PORTA. +- **Supported account types:** + - Nur eigener Tenant (**Single tenant**), oder + - **Multitenant** — dann passt typisch `Service_MSFT_TENANT_ID = common` zum Authority `login.microsoftonline.com/common`. +- Redirects werden unter **Authentication** ergänzt (nächster Abschnitt). + +--- + +## 2) Authentication — Redirect URIs (Web) + +**App registration** → **Authentication** → **Platform** „Web“ → **Redirect URIs**. + +Pro öffentlich erreichbare Gateway-URL **zwei** URIs (exakt, inkl. Schema): + +| URI | Env-Variable | +|-----|----------------| +| `{origin}/api/msft/auth/login/callback` | `Service_MSFT_AUTH_REDIRECT_URI` | +| `{origin}/api/msft/auth/connect/callback` | `Service_MSFT_DATA_REDIRECT_URI` | + +**In diesem Repo typische Origins** (jeweils beide URIs): + +- Lokal: `http://localhost:8000` +- INT: `https://gateway-int.poweron.swiss` +- PROD: `https://gateway-prod.poweron.swiss` +- Forgejo/ALT-Prod (falls genutzt): `https://api.poweron.swiss` + +Implizite Flow / SPA: für dieses Gateway-Backend-Redirect-Muster **nicht** nötig (Confidential Client mit Secret). + +Backend-Routing: `gateway/modules/routes/routeSecurityMsft.py` (Prefix `/api/msft`). + +--- + +## 3) Certificates & secrets + +**Certificates & secrets** → **New client secret**. + +Wert in `Service_MSFT_AUTH_CLIENT_SECRET` und `Service_MSFT_DATA_CLIENT_SECRET` eintragen (bei **einer** App-Registrierung für beide Flows: **dieselben** Secrets — in den Envs oft identisch). + +Verschlüsselung siehe [`encrypt-env-secrets.md`](encrypt-env-secrets.md). + +--- + +## 4) API permissions (Microsoft Graph — Delegated) + +**API permissions** → **Add a permission** → **Microsoft Graph** → **Delegated permissions**. + +Single Source of Truth für die Scope-Liste: `gateway/modules/auth/oauthProviderConfig.py` → `msftAuthScopes`, `msftDataScopes` + +| Zweck | Graph permissions (delegated) | +|-------|-------------------------------| +| Login (`msftAuthScopes`) | `User.Read` | +| Datenverbindung (`msftDataScopes`) | `User.Read`, `Mail.ReadWrite`, `Mail.Send`, `Files.ReadWrite.All`, `Sites.ReadWrite.All`, `Team.ReadBasic.All`, `OnlineMeetings.Read`, `Chat.ReadWrite`, `ChatMessage.Send`, `Calendars.Read`, `Contacts.Read` | + +Viele dieser Permissions erfordern **Administratoreinwilligung** im Tenant: **Grant admin consent for {tenant}**. + +Zusätzlicher Flow im Gateway: Admin-Consent-URL unter **`/api/msft/adminconsent`** mit Callback **`…/api/msft/adminconsent/callback`** (Redirect wird aus `Service_MSFT_DATA_REDIRECT_URI` abgeleitet — siehe `routeSecurityMsft.py`). + +--- + +## 5) Gateway — Env-Dateien anpassen + +| Variable | Bedeutung | +|----------|-----------| +| `Service_MSFT_AUTH_CLIENT_ID` | Application (client) ID für Login-Flow | +| `Service_MSFT_AUTH_CLIENT_SECRET` | Client secret (verschlüsselt) | +| `Service_MSFT_AUTH_REDIRECT_URI` | Muss **1:1** mit Entra Login-Redirect übereinstimmen | +| `Service_MSFT_DATA_CLIENT_ID` | Application (client) ID für Connect; darf = Auth sein | +| `Service_MSFT_DATA_CLIENT_SECRET` | Client secret (verschlüsselt) | +| `Service_MSFT_DATA_REDIRECT_URI` | Muss **1:1** mit Entra Connect-Redirect übereinstimmen | +| `Service_MSFT_TENANT_ID` | `common` (Multi-Tenant-Anmeldung) **oder** Verzeichnis-ID (GUID) des Tenants **poweron.swiss** für Single-Tenant-Authority | + +**Dateien (Stand Repo):** `gateway/env-gateway-dev.env`, `env-gateway-int.env`, `env-gateway-prod.env`, `env-gateway-prod-forgejo.env`, ggf. `gateway/.env`. + +Wenn neues **Frontend** oder neuer **API-Host**: + +- `APP_API_URL` — öffentliche Basis des Gateways. +- `APP_ALLOWED_ORIGINS` — CORS für das UI. + +--- + +## 6) Gateway — Python / Sicherheit (Referenz) + +| Datei | Inhalt | +|-------|--------| +| `gateway/modules/auth/oauthProviderConfig.py` | `msftAuthScopes`, `msftDataScopes`, `msftDataScopesForRefresh` | +| `gateway/modules/routes/routeSecurityMsft.py` | Login, Connect, Admin-Consent; liest alle `Service_MSFT_*` | +| `gateway/modules/auth/tokenManager.py` | Refresh für Microsoft Data (`Service_MSFT_DATA_*`, `Service_MSFT_TENANT_ID`) | +| `gateway/modules/auth/csrf.py` | CSRF-Ausnahmen für `/api/msft/auth/*` und `/api/msft/adminconsent*` — bei **neuen** OAuth-Pfaden ggf. erweitern (selten) | + +Keine Code-Änderung nötig, solange **gleiche Routen** und **gleiche Scope-Menge** wie in `oauthProviderConfig.py` verwendet werden. + +--- + +## 7) Smoke-Tests + +- [ ] Login mit Microsoft: Rückkehr ohne AADSTS50011 (Redirect mismatch) +- [ ] **Verbindungen** → Microsoft connect/reconnect +- [ ] Nach Tenant-Wechsel: Admin Consent im neuen Tenant ausgeführt +- [ ] Je nach Feature: Mail, OneDrive/SharePoint, Teams/Chat, Kalender, Kontakte kurz testen