Access SharePoitn with Graph
Access SharePoitn with Graph

Access SharePoint via Graph API in PowerShell

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.


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 typePermissions (from least to most privileged)
Delegated (work or school account)Reports.Read.All
Delegated (personal Microsoft account)Not supported.
ApplicationReports.Read.All
SharePointSiteUsage Method Screenshot Graph API
reportRoot: getSharePointSiteUsageDetail – Microsoft Graph v1.0 | Microsoft Docs

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

Register New App for Graph Api

Give your application a name, click on Accounts in this organizational directory only, select mobile as platform, after that click on register.

Application Registration for Graph Api

Take a note of the Application (client) ID, you will need it to authenticate against the Graph API.

Enterprise Application

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.

Enterprise Application API permission

Click on Microsoft Graph.

Graph API screenshot

Grant it Application permissions

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.

reports.read.all permission for Graph API

As you can see, the permission is not granted for this tenant.

not granted permissions screenshot for Graph API

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

Create client secret for Graph API enterprise application

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.

Usage Scripts client secret for Graph API

Take Note of the value! You wont see it again, if you leave the site.

Client Secret for Graph API obfuscated

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.

Global administrator account login to grant permission for Graph API

As you can see the permissions, which we have configured, are showing up:

permission grant for created app for Graph API

Since you have not set a redirect url, you will encounter this issue, which you can ignore.

this ocurs, since we have not configured a redirect url

Check Permission consent

You can check that the permission is granted, if you see the green check marks.

granted permission for enterprise application for Graph API

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.

PowerShell credential object

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
answer to the authorization request

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

Leave a Reply