113 lines
5.4 KiB
Markdown
113 lines
5.4 KiB
Markdown
# 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
|