Sometimes the use of PNP.PowerShell might not be sufficient. I encountered this experience, when I wanted to find out the usage of all sites. The Graph API provides methods, which you can use in your PowerShell Scripts. So in my example I wanted to get unused Sites with PowerShell. If you want to make use of it, you have to register an enterprise application and afterwards you can retrieve the information with an HTTP-Webrequest. In the following I will show you step by step how to access your SharePoint tenant with Graph API in PowerShell.
Table of Contents
Considerations – Find the right Graph API Method
The Graph API has multiple methods, which we can use to analyze and change the content of our M365 services. In order to find the right method for your plan, check folllowing resources to see what the Graph API is capable of Microsoft Graph REST API v1.0 reference – Microsoft Graph v1.0 | Microsoft Docs. Based on the needed methods, you have to set up your enterprise application.
Let’s assume, that you want to see the site usage of all sites in your tenant. In order to do this, you have to make use of following API method:
GET /reports/getSharePointSiteUsageDetail(period='{period_value}’)
GET /reports/getSharePointSiteUsageDetail(date={date_value})
This API requires following permissions. We will consider them in this article. I want to analyze the sharepoint usage and want to update it to a list afterwards, that’s why I will make use of Application – Reports.Read.All
Permission type | Permissions (from least to most privileged) |
---|---|
Delegated (work or school account) | Reports.Read.All |
Delegated (personal Microsoft account) | Not supported. |
Application | Reports.Read.All |
Register the Enterprise Application
After we figured out what permissions we need, we register the app.
Prerequisites
You have to have the role ‘Global Administrator’ to grant the permissions for an Enterprise Application.
Registration
Visit the Azure Portal URL and switdh to the app registrations sites. Directlink: App registrations – Microsoft Azure
Click on new registration
Give your application a name, click on Accounts in this organizational directory only, select mobile as platform, after that click on register.
Take a note of the Application (client) ID, you will need it to authenticate against the Graph API.
Grant API Permissions for App Registration
After creating the app, we have to give it the permissions, which we have defined in the first step.
Click on Microsoft Graph.
Grant it Application permissions
Now you have to select the permissions, for which you want to use the Graph API. I just need the information for Reports.Read.All. If you don’t know which permission to take, check the considerations part of this post.
As you can see, the permission is not granted for this tenant.
Create Client Secret for App Registration
In order to authenticate to the Graph API in PowerShell, you have to create a client secret.
Click on Certificates & secrets and then on New client secret
Set a Description and define when it will be expiring. I would recommend to give it a description, which you can recognize, for what it will be used in future. I have set 24 months, because I want to make use it in an automation, which should run for a long term. When finished, click Add.
Take Note of the value! You wont see it again, if you leave the site.
Consent the Requested permissions for App Registration
Caution: You have to consent the created application with the global administrator role.
https://login.microsoftonline.com/TENANTDomain/adminconsent?client_id=CLIENTID
The URL for my dev tenant is like:
https://login.microsoftonline.com/devmodernworkplace.onmicrosoft.com/adminconsent?client_id=949710fd-8d80-48ee-8c1b-a6f5e9e32be3
Choose an account with global administrator role.
As you can see the permissions, which we have configured, are showing up:
Since you have not set a redirect url, you will encounter this issue, which you can ignore.
Check Permission consent
You can check that the permission is granted, if you see the green check marks.
Script To Acess SharePoint via the Graph API (PowerShell)
The script contains two parts. The first part is about authentication and the second is about getting the data provided.
Authentication
I am making use of a credential export to be sure, that nobody steals the credentials, when it is in plain text. If you don’t know how to, check out: Use credentials in PowerShell – SPO Scripts
Function Export-CredentialFile { param( [Parameter(Mandatory=$true,Position=0)] $Username, [Parameter(Mandatory=$true,Position=1)] $Path ) While ($Path -eq "") { $Path = Read-Host "The path does not exist. Where should the credentials be exported to?" } $ParentPath = Split-Path $Path If ((Test-Path $ParentPath) -eq $false) { New-Item -ItemType Directory -Path $ParentPath } $Credential = Get-Credential($Username) $Credential | Export-Clixml -Path $Path Return $Credential } Function Import-CredentialFile ($Path) { if (! (Test-Path $Path)) { Write-Host "Could not find the credential object at $Path. Please export your credentials first" Export-CredentialFile } Import-Clixml -Path $Path } $AppId = '949710fd-8d80-48ee-8c1b-a6f5e9e32be3' $CredentialPath = "C:\temp\$AppId.key" Export-CredentialFile -Username $AppId -Path $CredentialPath
After doing this, we notice, that the file with the app id as name, has an encrypted password. So we splitted credentials from script to increase the security. This credential file can only be used on the machine and with the user, who has created it.
If we run follwing script afterwards, we will notice, that the $AuthorizationRequest will show us a token with an bearer token.
$AppId = '949710fd-8d80-48ee-8c1b-a6f5e9e32be3' $CredentialPath = "C:\temp\$AppId.key" $AppCredential = Import-CredentialFile -Path $CredentialPath $Scope = "https://graph.microsoft.com/.default" $Url = "https://login.microsoftonline.com/devmodernworkplace.onmicrosoft.com/oauth2/v2.0/token" $Body = @{ client_id = $AppCredential.UserName client_secret = $AppCredential.GetNetworkCredential().password scope = $Scope grant_type = 'client_credentials' } $AuthorizationRequest = Invoke-RestMethod -Uri $Url -Method 'post' -Body $Body $AuthorizationRequest
Access SharePoint Online with Authorization Token
Now that we got the access token, we can connect to SharePoint Online with following script. You can use the uris (methods), defined in Microsoft docs.
$Uri = "YOURURI" $Header = @{Authorization = "$($AuthorizationRequest.token_type) $($AuthorizationRequest.access_token)"} $SitesRequest = Invoke-RestMethod -Uri $Uri -Method 'Get' -Headers $Header
Get Site Usage Details
You can get the site usage with following uri “https://graph.microsoft.com/beta/reports/getSharePointSiteUsageDetail(period='{D90}’)?`$format=application/json”. The number next to the D means the amount of days. So for my example it shows the usage of all sites for the last 90 days. You can replace D90 with D7, D30, and D180.
With this script you can get the site usage for the last 90 days:
$Uri = "https://graph.microsoft.com/beta/reports/getSharePointSiteUsageDetail(period='{D90}')?`$format=application/json" $Header = @{Authorization = "$($AuthorizationRequest.token_type) $($AuthorizationRequest.access_token)"} $SitesRequest = Invoke-RestMethod -Uri $Uri -Method 'get' -Headers $Header $Sites.value | Out-GridView -PassThru
Bonus: Ready-to-Use Script
If you want to make use of the script, you have to change the parameters $GraphUrl and $AppID.
Param( $AppId = '949710fd-8d80-48ee-8c1b-a6f5e9e32be3', $GraphUrl = "https://login.microsoftonline.com/devmodernworkplace.onmicrosoft.com/oauth2/v2.0/token", $Scope = "https://graph.microsoft.com/.default", $Uri = "https://graph.microsoft.com/beta/reports/getOffice365GroupsActivityDetail`(`period=`'`D90`'`)?`$format=application/json", ) Function Export-CredentialFile { param( [Parameter(Mandatory=$true,Position=0)] $Username, [Parameter(Mandatory=$true,Position=1)] $Path ) While ($Path -eq "") { $Path = Read-Host "The path does not exist. Where should the credentials be exported to?" } $ParentPath = Split-Path $Path If ((Test-Path $ParentPath) -eq $false) { New-Item -ItemType Directory -Path $ParentPath } $Credential = Get-Credential($Username) $Credential | Export-Clixml -Path $Path Return $Credential } Function Import-CredentialFile ($Path) { if (! (Test-Path $Path)) { Write-Host "Could not find the credential object at $Path. Please export your credentials first" Export-CredentialFile } Import-Clixml -Path $Path } $CredentialPath = "C:\temp\$AppId.key" Export-CredentialFile -Username $AppId -Path $CredentialPath $AppCredential = Import-CredentialFile -Path $CredentialPath $Body = @{ client_id = $AppCredential.UserName client_secret = $AppCredential.GetNetworkCredential().password scope = $Scope grant_type = 'client_credentials' } $AuthorizationRequest = Invoke-RestMethod -Uri $GraphUrl -Method 'post' -Body $Body $Header = @{Authorization = "$($AuthorizationRequest.token_type) $($AuthorizationRequest.access_token)"} $SitesRequest = Invoke-RestMethod -Uri $Uri -Method 'get' -Headers $Header $SitesRequest.value | Out-GridView -PassThru
Conclusio
In this article you saw how to find the right permission for the enterprise application, which you need to access the SharePoint via the Graph API with PowerShell. After doing this, you can authenticate and analyze the data.
Further Docs
reportRoot: getSharePointSiteUsageDetail – Microsoft Graph v1.0 | Microsoft Docs
Pingback: Create SharePoint list items using Graph API (PowerShell)