Automating with PowerShell: Disabling anonymous reports for Office365

It’s been a while since I’ve blogged! I’ve been super busy with a secret project I am hoping to release soon. This blog is dedicated to a friend of mine.

His question was “Can we disable the anonymous report functionality in M365?” This functionality gives users a pseudo-anonymous ID in the M365 portal when reporting on Onedrive usage, but also when extracting this information via APIs. That can get annoying if you use the reports for monitoring functionality.

To change this function you can go to the portal and make the change, or you can use Evotec’s scripts here if you administer a single tenant. For multitenant situations, such as partners use, you can use the script below.

In this script, we use our Secure Application Model Exchange token to connect to the old admin portal resource API. We’re using this token because the Exchange Online application ID, and thus, the token is allowed to connect to all sorts of resources. The old admin portal API, but also the Azure AD API. All you have to change is the “Resource” ID in the request. There’s a bunch of available APIs with this so the trick to to just experiment 🙂

The script

$ApplicationId = 'AppID'
$ApplicationSecret = 'AppSecret'
$RefreshToken = 'RefreshTokens'
$ExchangeRefreshToken = 'YourExchangeRefreshToken'
$credential = New-Object System.Management.Automation.PSCredential($ApplicationId, ($ApplicationSecret | Convertto-SecureString -AsPlainText -Force))
$graphToken = New-PartnerAccessToken -ApplicationId $ApplicationId -Credential $credential -RefreshToken $refreshToken -Scopes '' -ServicePrincipal
write-host "Connecting to the Graph API to get all tenants." -ForegroundColor Green
$Contractheaders = @{ "Authorization" = "Bearer $($graphToken.accesstoken)" }  
$Customers = (Invoke-RestMethod -Uri "`$top=999" -Method GET -Headers $Contractheaders).value
foreach ($Customer in $Customers) {
    $uri = "$($Customer.tenant)/oauth2/token"
    $body = "resource=$($ExchangeRefreshToken)"
    $token = Invoke-RestMethod $uri -Body $body -ContentType "application/x-www-form-urlencoded" -ErrorAction SilentlyContinue -method post
    $sspr = Invoke-RestMethod -contenttype "application/json;charset=UTF-8" -uri '' -body '{"PrivacyEnabled":false,"PowerBiEnabled":true}' -method POST -Headers @{
        Authorization            = "Bearer $($token.access_token)";
        "x-ms-client-request-id" = [guid]::NewGuid().ToString();
        "x-ms-client-session-id" = [guid]::NewGuid().ToString()
        'x-ms-correlation-id'    = [guid]::NewGuid()
        'X-Requested-With'       = 'XMLHttpRequest'

And that’s it! as always, Happy PowerShelling. 🙂


  1. Robbie November 4, 2021 at 10:03 am

    There appears to be a typo here:
    $uri = “$($Customer.tenant)/oauth2/token”
    as “tenant” is not a value, I changed this to “Customer.CustomerID” and it worked.

  2. Damien December 29, 2021 at 4:11 pm

    Hi, thanks, but if we have more than 999 tenantid, what is the query parameter to add :(?

Leave a comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.