Microsoft Graph, mit Delegated Permissions und PowerShell Daten abfragen

In Microsoft Graph gibt es zwei Arten wie sich jemand über eine Azure App authentifizieren kann. Entweder über Delegated Permissions oder Application Permissions. In dem Beitrag findest du Details wie du über PowerShell mit Delegated Permissions umgehen kannst.

Für PowerShell Scripts kommen meist Application Permissions zum Einsatz. Application Permissions laufen ohne Benutzeraktion ab. Delegated Permissions laufen im Namen des angemeldeten Benutzers. Für Details über Application und Delegated Permissions findest du hier mehr Informationen. Der Umgang mit Daten aus dem Tenant ist via Application Permissions mit PowerShell einfacher und die meisten APIs von Microsoft Graph bieten Rechte für Application und Delegated an. Aber nicht alle APIs, zum Beispiel die von Planner. Für APIs von Planner gibt es nur die Option via Delegated Permissions. Als Beispiel die List tasks API um alle Planner Tasks einer M365-Gruppe abzurufen.

Falls du voten willst, in UserVoice gibt es den Wunsch nach Application Permissions für Planner APIs.
Nachfolgend eine Anleitung wie du mit PowerShell alle Planner Tasks einer M365-Gruppe abfragen kannst. Für andere APIs mit Delegated ist es ein ähnliches Vorgehen. Nachlesen kannst du es hier.


  • Wie immer benötigst du in Azure eine Azure App mit den in der API beschriebenen Berechtigungen für Microsoft Graph. Achte bei der Erstellung der App darauf das es sich um eine Web App handelt, oder füge die Platform Web einer bestehenden App hinzu.
  • Ich erstellte mir für die Demo eine neue App „Azure Planner App“ mit den zwei erforderlichen Rechten „Group.Read.All, Group.ReadWrite.All“ im Delegated Modus. Für die zwei Berechtigungen ist es erforderlich das ein Global Admin die Rechte für den Tenant freigeben muss, sonst kannst du nur Daten für deinen Account beziehen.
  • Die neue App liefert eine AppID die du wissen musst.
  • Wichtig bei Delegated Apps ist darauf zu achten was du als Redirect URI angibst. Die URI brauchst du später um den Code für die Authentifizierung zu beziehen. Für die Verwendung mit PowerShell ist localhost ausreichend.
  • Du musst in der App ausserdem noch einen Client Secret anlegen, um später einen Authentifizierungstoken zu erhalten. Achte bei der Erstellung des Secrets auf das Passwort. Es wird dir nur einmal angezeigt damit du es kopieren kannst. Hast du es vergessen musst du einen neuen Secret anlegen.
  • Ich empfehle dir ausserdem für die App mehrere Besitzer zu definieren.
  • Mit den Angaben hast du soweit alles um über die App die Planner-Daten aus Microsoft Graph abzurufen.

Was du noch wissen solltest. Der ausführende Account muss ein Mitglied der M365-Gruppe sein. Da du die Abfrage bei Delegated Permissions im Namen des Accounts ausführst muss er ein Mitglied der Gruppe sein, sonst hat der Account keinen Zugriff auf die Daten des Plans.
Nachfolgend Codezeilen um mit den Angaben die Daten abzurufen. Achte darauf die Angaben für deine App anzupassen. Möchtest du den Code lieber als Datei runterladen kannst du es hier bekommen.

PowerShell
# A sample for my post at https://go.topedia.com/ViBHj
# Hier musst du deine Angaben ergänzen
$M365Groupname = '[M365Gruppenname]'
$TenantUrl = '[TenantName].onmicrosoft.com'
$AppClientID = '[AzureAppClientID]'
$AppClientSecret = '[AzureAppClientSecret]' # Du könntest den Secret auch verschlüsselt speichern, beachte dafür https://308.ch/fohrb
$AppRedirectUri = 'http://localhost/myapp/' 

# Im ersten Teil musst du einen Autorisierungscode beziehen. Damit eine Benutzerinteraktion möglich ist wird Windows Forms verwendet.
Add-Type -AssemblyName System.Windows.Forms
$AuthUrl  = "https://login.microsoftonline.com/$TenantUrl/oauth2/v2.0/authorize" +
                '?client_id='    + $AppClientID +
                '&scope='        + 'Group.Read.All Group.ReadWrite.All' +
                '&redirect_uri=' + $AppRedirectUri  +
                '&response_type=code' +
		'&response_mode=query' +
		'&state=' + (Get-Random)

# Delegated Permissions benötigen eine Benutzerinteraktion um sich anzumelden oder die Verwendung der Azure App zu bestätigen. Dafür erstellst du eine Art Pop-up um die Anmeldemaske zu sehen. 
$AuthForm = New-Object -TypeName System.Windows.Forms.Form  -Property @{ Width = 600; Height = 600 }
$WebBrowser = New-Object -TypeName System.Windows.Forms.WebBrowser -Property @{ Width = 600; Height = 600; Url = $AuthUrl }

$DocComp  = { $Script:WebUrl = $WebBrowser.Url.AbsoluteUri
	if ($Script:WebUrl -match 'error=[^&]*|code=[^&]*')	 
	{$AuthForm.Close() }
}

$WebBrowser.Add_DocumentCompleted($DocComp) 
$AuthForm.Controls.Add($WebBrowser)            
$AuthForm.Add_Shown({$AuthForm.Activate()})
$AuthForm.ShowDialog() | Out-Null

# Falls deine interne Konfiguration kein Single Sign-on unterstützt kannst du hier eventuell ein Anmeldefenster sehen. Melde dich mit deinem Account an. 

# War die Konfiguration zuvor korrekt hast du nun einen Autorisierungscode erhalten. Mit dem Code kannst du im zweiten Schritt von Azure einen Authentifizierungstoken beziehen, den du zum Abruf der Planner-Daten benötigst. 
$AuthCode = $null
if( $WebUrl -match "code=([^&]*)")
{ $AuthCode = $Matches[1] } 


if($AuthCode -ne $null)
{
	$AuthTokenBody = @{ 
		'grant_type'  = 'authorization_code'
		'code' = $AuthCode
		'client_id' = $AppClientID
		'redirect_uri' = $AppRedirectUri
		'scope' = 'Group.Read.All Group.ReadWrite.All'
		'client_secret' = $AppClientSecret
	}

	$AuthTokenUrl = "https://login.microsoftonline.com/$TenantUrl/oauth2/v2.0/token"
	$AuthToken = Invoke-RestMethod -Method Post -Uri $AuthTokenUrl  -Body $AuthTokenBody
	$AuthHeader = @{ Authorization = "$($AuthToken.token_type) $($AuthToken.access_token)" }

        # War bis hierher alles gut hast du nun den Authentifizierungstoken erhalten und kannst mit dem Token Daten aus der Planner-API abrufen. Beachte, der Token ist zeitlich befristet gültig. 

        # Du benötigst die ID der M365-Gruppe
	$RestUrl = ('https://graph.microsoft.com/v1.0/groups?



Hast du alles korrekt ausgeführt listet es die Planner Tasks der M365-Gruppe. 



Planner Tasks – PowerShell vs. Web




Auf dieselbe Art kannst du die Tasks weiter verarbeiten, zum Beispiel Filtern nach Fälligkeitsdatum, die Tasks mit PowerShell anpassen, löschen, und mehr. Achte auf die verfügbaren Planner-APIs. 
Zusatzhinweis, die Auflistung aller Tasks pro Account wird im Moment nicht unterstützt, obwohl es die API gibt. Es tritt ein Berechtigungsfehler auf.
 + "filter=displayName eq '" + $M365Groupname + "'")
	$RestResults  = Invoke-RestMethod -Method Get  -Headers $AuthHeader  -Uri $RestUrl -ContentType 'application/json'

        # Du benötigst die ID des Planner Plans. Beachte das eine M365-Gruppe mehrere Pläne haben kann.
	$RestUrl = ('https://graph.microsoft.com/v1.0/groups/' + $RestResults.value.id + '/planner/plans')
	$RestResults  = Invoke-RestMethod -Method Get  -Headers $AuthHeader  -Uri $RestUrl -ContentType 'application/json'

        # Mit der ID des Planner Plans kannst du die Aufgaben des Plans abrufen
	$RestUrl = ('https://graph.microsoft.com/v1.0/planner/plans/' + $RestResults.value.id + '/tasks') 
	$RestResults  = Invoke-RestMethod -Method Get  -Headers $AuthHeader  -Uri $RestUrl -ContentType 'application/json'
	$RestResults.value | select Title

} else
{ Write-Host "AuthCode not received" -f red  }

Hast du alles korrekt ausgeführt listet es die Planner Tasks der M365-Gruppe.

Planner Tasks – PowerShell vs. Web
Planner Tasks – PowerShell vs. Web

Auf dieselbe Art kannst du die Tasks weiter verarbeiten, zum Beispiel Filtern nach Fälligkeitsdatum, die Tasks mit PowerShell anpassen, löschen, und mehr. Achte auf die verfügbaren Planner-APIs.
Zusatzhinweis, die Auflistung aller Tasks pro Account wird im Moment nicht unterstützt, obwohl es die API gibt. Es tritt ein Berechtigungsfehler auf.

Share this post:

About the Author

Tobias Asböck

Tobias Asböck

Tobias is a Senior System Engineer with more than 10 years of professional experience with Microsoft 365 products such as SharePoint Online, OneDrive for Business, Teams Collaboration, Entra ID, Information Protection, Universal Print, and Microsoft 365 Licensing. He also has 15+ years of experience planning, administering, and operating SharePoint Server environments. In his spare time, Tobias is busy with updates in the Microsoft 365 world or on the road with his road bike and other sports activities. If you have additional questions, please contact me via LinkedIn or support@topedia.com.

1 Comment

  1. Ingo
    Sehr schön erklärt – Danke