Get-GraphToken #
ÜBERSICHT #
Holt ein Microsoft Graph API Access-Token (Service- oder User-Flow).
SYNTAX #
Get-GraphToken -ServiceFlow [-Conn] <__ComObject> [-TenantId] <string> [[-ClientId] <string>]
[-ClientSecret] <string> [[-Scope] <string>] [[-UserScope] <string>] [[-RedirectUri] <string>]
[[-TokenPath] <string>]
BESCHREIBUNG #
Zentrale Token-Funktion für alle Graph-API-Operationen. Unterstützt zwei Flows:
Service-Flow (Client Credentials): Direkter Token-Abruf ohne Benutzerinteraktion. Geeignet für Server, Cronjobs und Hintergrundprozesse. Hat Zugriff auf alle Postfächer im Tenant. Benötigt TenantId, ClientId und ClientSecret.
User-Flow (OAuth2 PKCE): Interaktive Anmeldung über den Browser. Beim ersten Aufruf öffnet sich der Browser zur Anmeldung, danach läuft alles automatisch per Refresh-Token. Zugriff nur auf das eigene Postfach (/me). Benötigt nur die ClientId.
EINRICHTUNG IM AZURE PORTAL (https://portal.azure.com) #
SCHRITT 1: App registrieren Azure Portal -> “Microsoft Entra ID” -> “App-Registrierungen” -> “Neue Registrierung” - Name: z.B. “EULANDA Graph” - Kontotypen: “Nur Konten in diesem Organisationsverzeichnis” - Registrieren -> Die “Anwendungs-ID (Client)” auf der Übersichtsseite ist die ClientId -> Die “Verzeichnis-ID (Mandant)” ist die TenantId
SCHRITT 2: API-Berechtigungen hinzufügen App -> “API-Berechtigungen” -> “Berechtigung hinzufügen” -> “Microsoft Graph”
Für den SERVICE-FLOW (“Anwendungsberechtigungen” wählen):
- Mail.Send (zum E-Mail-Versand)
- Contacts.ReadWrite (zum Kontakt-Sync) -> Danach “Administratorzustimmung erteilen” klicken (Pflicht!)
Für den USER-FLOW (“Delegierte Berechtigungen” wählen):
- Mail.Send
- Contacts.ReadWrite
- offline_access (für automatische Token-Erneuerung) -> Administratorzustimmung ist optional, Benutzer kann selbst zustimmen
SCHRITT 3a: Client Secret erstellen (nur für Service-Flow)
App -> “Zertifikate und Geheimnisse” -> “Neuer geheimer Clientschlüssel”
- Beschreibung und Ablaufdatum wählen
- “Hinzufügen” -> Den “Wert” sofort kopieren (wird nur einmal angezeigt!) = ClientSecret
SCHRITT 3b: Redirect-URI einrichten (nur für User-Flow)
App -> “Authentifizierung” -> “Plattform hinzufügen”
- “Mobilgerät- und Desktopanwendungen” wählen (NICHT “Web”!)
- Benutzerdefinierte Redirect-URI eingeben: http://localhost:8080/ -> Unter “Erweiterte Einstellungen”: “Öffentliche Clientflows zulassen” auf JA setzen
- Speichern
Beide Flows können parallel in derselben App eingerichtet werden. Die App braucht dann sowohl das Client Secret (Schritt 3a) als auch die Redirect-URI (Schritt 3b).
VERWENDUNG #
Die Funktion ist symmetrisch aufgebaut: zwei Achsen legen den Modus fest.
-ServiceFlowgesetzt -> Service-Flow (Client Credentials). Fehlt der Switch -> User-Flow (OAuth2 PKCE).-Conngesetzt -> Credentials aus SQL-Registry. Fehlt-Conn-> alle nötigen Werte als Parameter übergeben.
Service-Flow aus Registry (empfohlen für Server, Cronjob, ABO-Lauf): $token = Get-GraphToken -ServiceFlow -Conn $conn
Service-Flow explizit (Ad-hoc-Skript ohne EULANDA-DB): $token = Get-GraphToken -ServiceFlow ` -TenantId ‘54197dd8-…’ -ClientId ‘c081dca9-…’ -ClientSecret ‘…’
User-Flow aus Registry (Arbeitsplatz mit EULANDA-Setup): $token = Get-GraphToken -Conn $conn
User-Flow explizit (Test, externes Skript): $token = Get-GraphToken -UserScope ‘Mail.Send offline_access’
PARAMETER #
-ServiceFlow #
Type: switch
Schalter, der zwischen Service-Flow (Client Credentials) und User-Flow (OAuth2 PKCE) unterscheidet. Ist der Switch gesetzt, wird der Service-Flow ausgeführt; fehlt er, läuft der User-Flow. In Kombination mit -Conn werden die Credentials aus der SQL-Registry gelesen (Set ServiceRegistry), ohne -Conn müssen -TenantId, -ClientId und -ClientSecret als Parameter übergeben werden (Set ServiceExplicit).
Der Service-Flow aus Registry (-ServiceFlow -Conn $conn) ist der
empfohlene Weg für automatisierten Server-Versand (ABO-Läufe,
Scheduled Tasks, Cronjobs): Credentials bleiben zentral in der
EULANDA-Registry, das PowerShell-Skript braucht keine Secrets im Klartext.-Conn #
Type: __ComObject
ADODB-Verbindungsobjekt zur EULANDA-Datenbank. Steuert, ob Credentials aus der Registry gelesen werden:
- Zusammen mit
-ServiceFlow-> liestClientId,ClientSecret,TenantIdund optionalScopeaus\SYSTEM\Devices\EMail\GraphAPI\ServiceFlow. - Ohne
-ServiceFlow(User-Flow) -> liestClientId,TenantIdundUserScopeaus\SYSTEM\Devices\EMail\GraphAPI\UserFlowals Overrides. - Explizit per Parameter übergebene Werte haben Vorrang vor Registry-Werten, leere Registry-Werte lassen den Default stehen.
Beim Service-Flow aus Registry müssenClientId,ClientSecretundTenantIdvorhanden sein – fehlen Werte, wird ein klarer Fehler mit der Liste der fehlenden Felder geworfen.
-TenantId #
Type: string
Azure Verzeichnis-ID (Mandanten-ID). Zu finden im Azure Portal unter “Microsoft Entra ID” -> “Übersicht” oder auf der Übersichtsseite der App. Nur im Set ServiceExplicit erforderlich (Service-Flow ohne -Conn).
-ClientId #
Type: string
Default: 'c081dca9-2f08-475a-8691-5339e99ab42c'
Anwendungs-ID (Client-ID) der registrierten Azure-App. Zu finden im Azure Portal unter App-Registrierungen -> [App-Name] -> “Übersicht”. Im ServiceExplicit-Set Pflicht, im User-Flow optional mit Default auf die EULANDA-Standard-App. Im UserRegistry-Set überschreibt ein expliziter Parameter den Registry-Wert.
-ClientSecret #
Type: string
Geheimer Clientschlüssel der Azure-App. Wird unter “Zertifikate und Geheimnisse” erstellt. Der Wert wird nur einmal angezeigt – sofort kopieren! Nur im Set ServiceExplicit erforderlich.
-Scope #
Type: string
Default: 'https://graph.microsoft.com/.default'
OAuth2 Scope für den Service-Flow. Default: “https://graph.microsoft.com/.default" (alle konfigurierten Application Permissions). Muss normalerweise nicht geändert werden. Im ServiceRegistry-Set kann der Scope auch aus der Registry (Scope) gelesen werden; ein expliziter Parameter überschreibt den Registry-Wert.
-UserScope #
Type: string
OAuth2 Scope für den User-Flow. Leerzeichen-getrennte Liste der benötigten Berechtigungen. “offline_access” sollte immer dabei sein (für Refresh-Token). Im Set UserExplicit Pflicht, im Set UserRegistry optional – dort fällt die Funktion zurück auf den Registry-Wert (UserScope unter \GraphAPI\UserFlow) und bei leerem Registry-Eintrag auf den EULANDA-Standard “Mail.Send Contacts.ReadWrite offline_access”.
Beispiele: “Contacts.ReadWrite offline_access” (Kontakt-Sync) “Mail.Send offline_access” (E-Mail-Versand) “User.Read Mail.Send offline_access” (E-Mail mit Absender-Abfrage) “Contacts.ReadWrite Mail.Send offline_access” (beides)
-RedirectUri #
Type: string
Default: 'http://localhost:8080/'
Redirect-URI für den User-Flow. Default: “http://localhost:8080/”. Muss exakt mit der im Azure Portal konfigurierten URI übereinstimmen.
-TokenPath #
Type: string
Pfad zur Token-Datei für den User-Flow. Default: automatisch aus Scope abgeleitet ($env:APPDATA\Eulanda\graph-{scope-hash}.json). Verschiedene Scopes verwenden automatisch verschiedene Token-Dateien.
AUSGABEN #
string
Der access_token (Bearer-Token) als String. Kann direkt als Authorization-Header verwendet werden: “Bearer $token”
BEISPIELE #
# Service-Flow aus SQL-Registry (empfohlen für Server-/Batch-Betrieb).
# ClientId, ClientSecret und TenantId liegen zentral in der EULANDA-Registry
# unter \SYSTEM\Devices\EMail\GraphAPI\ServiceFlow -- kein Secret im Skript.
$conn = New-Object -ComObject ADODB.Connection
$conn.Open('File Name=C:\Eulanda\EULANDA_1 Mustermann.udl')
$token = Get-GraphToken -ServiceFlow -Conn $conn
Send-GraphMail -Token $token -AuthFlow Service -Conn $conn `
-To 'kunde@beispiel.de' -Subject 'Monats-Rechnung' `
-HtmlBody '<b>Siehe Anhang</b>' -Attachments 'C:\Temp\rechnung.pdf'
# -From entfällt -- wird aus \GraphAPI\ServiceFlow\From gezogen
# Service-Flow explizit (Ad-hoc-Skript ohne EULANDA-DB)
$token = Get-GraphToken -ServiceFlow `
-TenantId '54197dd8-9c79-46ca-9d1f-a6c260a7cfab' `
-ClientId 'c081dca9-2f08-475a-8691-5339e99ab42c' `
-ClientSecret 'Ihr~ClientSecret-hier'
# Damit auf ein bestimmtes Postfach zugreifen (z.B. Kontakt-Sync):
Export-ContactToOutlook -Token $token -Conn $conn `
-AddressMatch 'MUSTERKUNDE' -FolderName 'EULANDA' -CreateFolder `
-UserEmail 'benutzer@firma.de'
# User-Flow aus Registry: alle Werte aus \GraphAPI\UserFlow
# (ClientId, TenantId, UserScope). Nützlich am EULANDA-Arbeitsplatz --
# zentrale Konfiguration, kein Scope im Skript.
$conn = New-Object -ComObject ADODB.Connection
$conn.Open('File Name=C:\Eulanda\EULANDA_1 Mustermann.udl')
$token = Get-GraphToken -Conn $conn
# User-Flow aus Registry mit Scope-Override: für einen Spezial-Scope
# den Registry-Scope übersteuern, ClientId/TenantId bleiben aus Registry.
$token = Get-GraphToken -Conn $conn -UserScope 'Calendars.ReadWrite'
# User-Flow explizit: Interaktive Anmeldung ohne EULANDA-DB
$token = Get-GraphToken -UserScope 'Contacts.ReadWrite offline_access'
# -> Browser öffnet sich, als eigener Benutzer anmelden
# -> Token wird gespeichert, nächster Aufruf braucht keinen Browser mehr
# -> ClientId fällt auf EULANDA-Standard-App zurück
# Damit auf das eigene Postfach zugreifen (kein -UserEmail nötig):
Export-ContactToOutlook -Token $token -Conn $conn `
-AddressMatch 'MUSTERKUNDE' -FolderName 'EULANDA' -CreateFolder
# Token-Cache löschen (z.B. bei Benutzer-Wechsel) und neu anmelden
Remove-Item "$env:APPDATA\Eulanda\graph-*" -Force
$token = Get-GraphToken -UserScope 'Contacts.ReadWrite offline_access'
# -> Browser öffnet sich erneut zur Anmeldung
HINWEISE #
Übersicht der vier ParameterSets:
| Merkmal | ServiceRegistry | ServiceExplicit | UserRegistry | UserExplicit |
|---|---|---|---|---|
| Switch/Conn | -ServiceFlow + -Conn | -ServiceFlow | -Conn | (keins von beiden) |
| Pflicht-Parameter | - | TenantId+ClientId+Secret | - | UserScope |
| Credentials-Quelle | \GraphAPI\ServiceFlow | Parameter | \GraphAPI\UserFlow + Defaults | Parameter + Defaults |
| Interaktion | Keine | Keine | Browser (einmalig) | Browser (einmalig) |
| Token-Cache | Keiner (jedes Mal neu) | Keiner (jedes Mal neu) | Datei mit Refresh-Token | Datei mit Refresh-Token |
| API-Pfad | /users/{email}/… | /users/{email}/… | /me/… | /me/… |
| From nötig | Ja (aus Registry) | Ja | Nein (eigene Mailbox) | Nein (eigene Mailbox) |
| Azure Permission | Anwendungsberechtigung | Anwendungsberechtigung | Delegierte Berechtigung | Delegierte Berechtigung |
| Admin-Consent nötig | Ja | Ja | Nein | Nein |
| Postfach-Zugriff | Alle im Tenant | Alle im Tenant | Nur eigenes + Shared | Nur eigenes + Shared |
| Typischer Einsatz | Server, ABO-Lauf, Cron | Ad-hoc Skript | Arbeitsplatz, EULANDA-PC | Test, externes Skript |
Registry-Schema (EULANDA-SQL-Registry):
\SYSTEM\Devices\EMail\GraphAPI
AuthFlow = "User" | "Service" # Default für UI-Versand (Delphi-Seite)
\SYSTEM\Devices\EMail\GraphAPI\UserFlow
ClientId, TenantId, UserScope, From # alle optional (Fallbacks greifen)
\SYSTEM\Devices\EMail\GraphAPI\ServiceFlow
ClientId, ClientSecret, TenantId, From # Credentials-Felder Pflicht
Scope # optional
Die alten Root-Level-Values unter \GraphAPI werden nicht mehr gelesen.