%3CLINGO-SUB%20id%3D%22lingo-sub-1741127%22%20slang%3D%22en-US%22%3EHow%20to%20retrieve%20complete%20set%20of%20permission%20changes%20while%20utilizing%20DeltaLinks%20(tokens)%20in%20SPO%3F%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1741127%22%20slang%3D%22en-US%22%3E%3CP%3EDelta%20is%2C%20by%20default%2C%20a%20user-scoped%20API%20to%20drive%20sync-like%20behavior.%20It%20scopes%20its%20results%20down%20to%20the%20set%20of%20changes%20which%20are%20definitely%20impactful%20to%20the%20caller.%20It%20filters%20out%20changes%20which%20it%20knows%20are%20irrelevant%20to%20the%20caller.%20When%20the%20API%20cannot%20definitely%20determine%20relevance%20cheaply%2C%20e.g.%20when%20it%20needs%20to%20make%20a%20full%20permission%20enumeration%20to%20verify%2C%20it%20will%20include%20the%20result%2C%20even%20though%20it%20might%20not%20be%20relevant%20to%20the%20caller.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EDelta%20attempts%20to%20scope%20permission-based%20changes%20to%20those%20relevant%20to%20the%20caller.%20If%20the%20caller's%20access%20wasn't%20altered%20by%20the%20permission%20change%2C%20the%20item%20may%20not%20be%20included%20in%20the%20delta%20results.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EClients%20which%20are%20trying%20to%20enumerate%20all%20permission%20changes%20should%20make%20sure%20the%20follow%20the%20recommendations%20in%20aka.ms%2Fscanguidance.%20Namely%2C%20there%20are%20specific%20authentication%20requirements%20and%20specific%20Prefer%20headers%20that%20need%20to%20be%20provided%2C%20and%20failure%20to%20do%20so%20will%20result%20in%20permission%20changes%20being%20scoped%20down.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThe%20only%20way%20to%20receive%20the%20complete%20set%20of%20changes%20is%20to%20use%20app-only%20authentication%20with%20the%20Sites.FullControl.All%20scope%20and%20pass%20header%20%22Prefer%22%3D%22deltashowsharingchanges%2Chierarchicalsharing%22.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3ESteps%3A%3C%2FP%3E%0A%3CP%3E1%5D%20Create%20an%20App%20in%20AAD%20with%20Sites.FullControl.All%20Application%20permission%2C%20see%20screen%20shot%20below%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22SPDev_Support_0-1601681126806.png%22%20style%3D%22width%3A%20400px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F223839i74452F53F9322491%2Fimage-size%2Fmedium%3Fv%3D1.0%26amp%3Bpx%3D400%22%20title%3D%22SPDev_Support_0-1601681126806.png%22%20alt%3D%22SPDev_Support_0-1601681126806.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%3CBR%20%2F%3E2%5D%20Sample%20powershell%20script%20to%20generate%20the%20Access%20token%20and%20the%20delta%20token%20link%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-powershell%22%3E%3CCODE%3E%26lt%3B%23%0ACode%20Example%20Disclaimer%3A%0ASample%20Code%20is%20provided%20for%20the%20purpose%20of%20illustration%20only%20and%20is%20not%20intended%20to%20be%20used%20in%20a%20production%20environment.%0ATHIS%20SAMPLE%20CODE%20AND%20ANY%20RELATED%20INFORMATION%20ARE%20PROVIDED%20%22AS%20IS%22%20WITHOUT%20WARRANTY%20OF%20ANY%20KIND%2C%20EITHER%20EXPRESSED%20OR%20IMPLIED%2C%0AINCLUDING%20BUT%20NOT%20LIMITED%20TO%20THE%20IMPLIED%20WARRANTIES%20OF%20MERCHANTABILITY%20AND%2FOR%20FITNESS%20FOR%20A%20PARTICULAR%20PURPOSE.%0AWe%20grant%20You%20a%20nonexclusive%2C%20royalty-free%20right%20to%20use%20and%20modify%20the%20Sample%20Code%20and%20to%20reproduce%20and%20distribute%20the%20object%0Acode%20form%20of%20the%20Sample%20Code%2C%20provided%20that.%20You%20agree%3A%20(i)%20to%20not%20use%20Our%20name%2C%20logo%2C%20or%20trademarks%20to%20market%20Your%20software%0Aproduct%20in%20which%20the%20Sample%20Code%20is%20embedded%3B%20(ii)%20to%20include%20a%20valid%20copyright%20notice%20on%20Your%20software%20product%20in%20which%20the%0ASample%20Code%20is%20embedded%3B%20and%20(iii)%20to%20indemnify%2C%20hold%20harmless%2C%20and%20defend%20Us%20and%20Our%20suppliers%20from%20and%20against%20any%20claims%20or%0Alawsuits%2C%20including%20attorneys%20fees%2C%20that%20arise%20or%20result%20from%20the%20use%20or%20distribution%20of%20the%20Sample%20Code.%0A%23%26gt%3B%0A%0Acls%0A%0A%24host.Runspace.ThreadOptions%20%3D%20%22ReuseThread%22%0A%0AWrite-Host%20%22STARTED%20at%22%20(Get-Date).ToString()%20-f%20Green%0A%0A%24ClientID%20%3D%20%22fa9737d5-5a3e-4fab-0000-000000000000%22%0A%24ClientSecret%20%3D%20%221JOe%3AM8HBBUz-0000000000000000000%22%0A%24scope%3D%20%22https%3A%2F%2Fgraph.microsoft.com%2F.default%22%0A%24POSTURI%20%3D%20%20%22https%3A%2F%2Flogin.microsoftonline.com%2Fd6f932a7-5f74-0000-0000-000000000000%2Foauth2%2Fv2.0%2Ftoken%22%0A%0A%24body%20%3D%20%40%7Bgrant_type%3D%22client_credentials%22%3Bclient_id%3D%24ClientID%3Bclient_secret%3D%24ClientSecret%3Bscope%3D%24scope%7D%0A%0A%24oauth%20%3D%20Invoke-RestMethod%20-Method%20Post%20-Uri%20%24POSTURI%20-Body%20%24body%0A%0A%24graphAccessToken%20%3D%20%24oauth.access_token%0A%0AWrite-Host%20%22Access%20token%3A%20%24(%24graphAccessToken)%22%0A%0A%24requestHeader%20%3D%20%40%7B%0A%0A%20%20%22Authorization%22%20%3D%20%22Bearer%20%24graphAccessToken%22%0A%20%20%22Content-Type%22%20%3D%20%22application%2Fjson%22%0A%20%20%22Prefer%22%20%3D%20%22deltashowsharingchanges%2Chierarchicalsharing%2Cdeltatraversepermissiongaps%2Cdeltashowremovedasdeleted%22%0A%7D%0A%0A%24Uri%20%3D%20%22https%3A%2F%2Fgraph.microsoft.com%2Fv1.0%2Fsites%2Fspotenant.sharepoint.com%2Cdf6ba610-b132-0000-0000-000000000000%2Ce0dbcdc6-0637-4246-0000-000000000000%2Fdrive%2Froot%2Fdelta%3Flatest%22%20%0A%0A%24Result%20%3D%20(Invoke-RestMethod%20-Method%20Get%20-Headers%20%24requestheader%20-Uri%20%24Uri)%0A%0A%24deltaUri%20%3D%20%24Result.'%40odata.deltaLink'%0A%0AWrite-Host%20%24deltaUri%0AWrite-Host%20%22DONE%20at%22%20(Get-Date).ToString()%20-f%20Green%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E3%5D%20Copy%20the%20Access%20token%20and%20the%20deltaUri%20value%20output%20from%20the%20above%20script%20and%20use%20them%20in%20the%20following%20sample%20powershell%20script%20to%20retrieve%20the%20complete%20set%20of%20permission%20changes%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-powershell%22%3E%3CCODE%3E%26lt%3B%23%0ACode%20Example%20Disclaimer%3A%0ASample%20Code%20is%20provided%20for%20the%20purpose%20of%20illustration%20only%20and%20is%20not%20intended%20to%20be%20used%20in%20a%20production%20environment.%0ATHIS%20SAMPLE%20CODE%20AND%20ANY%20RELATED%20INFORMATION%20ARE%20PROVIDED%20%22AS%20IS%22%20WITHOUT%20WARRANTY%20OF%20ANY%20KIND%2C%20EITHER%20EXPRESSED%20OR%20IMPLIED%2C%0AINCLUDING%20BUT%20NOT%20LIMITED%20TO%20THE%20IMPLIED%20WARRANTIES%20OF%20MERCHANTABILITY%20AND%2FOR%20FITNESS%20FOR%20A%20PARTICULAR%20PURPOSE.%0AWe%20grant%20You%20a%20nonexclusive%2C%20royalty-free%20right%20to%20use%20and%20modify%20the%20Sample%20Code%20and%20to%20reproduce%20and%20distribute%20the%20object%0Acode%20form%20of%20the%20Sample%20Code%2C%20provided%20that.%20You%20agree%3A%20(i)%20to%20not%20use%20Our%20name%2C%20logo%2C%20or%20trademarks%20to%20market%20Your%20software%0Aproduct%20in%20which%20the%20Sample%20Code%20is%20embedded%3B%20(ii)%20to%20include%20a%20valid%20copyright%20notice%20on%20Your%20software%20product%20in%20which%20the%0ASample%20Code%20is%20embedded%3B%20and%20(iii)%20to%20indemnify%2C%20hold%20harmless%2C%20and%20defend%20Us%20and%20Our%20suppliers%20from%20and%20against%20any%20claims%20or%0Alawsuits%2C%20including%20attorneys%20fees%2C%20that%20arise%20or%20result%20from%20the%20use%20or%20distribution%20of%20the%20Sample%20Code.%0A%23%26gt%3B%0A%0Acls%0A%0A%24host.Runspace.ThreadOptions%20%3D%20%22ReuseThread%22%0A%0AWrite-Host%20%22STARTED%20at%22%20(Get-Date).ToString()%20-f%20Green%0A%0A%24graphAccessToken%20%3D%20%22copied%20from%20output%20of%20above%20sample%20powershell%20script%22%0A%0A%24requestHeader%20%3D%20%40%7B%0A%20%20%22Authorization%22%20%3D%20%22Bearer%20%24graphAccessToken%22%0A%20%20%22Content-Type%22%20%3D%20%22application%2Fjson%22%0A%20%20%22Prefer%22%20%3D%20%22deltashowsharingchanges%2Chierarchicalsharing%22%0A%7D%0A%0AWrite-Host%0A%0A%24deltaUri%20%3D%20%22copied%20from%20output%20of%20above%20sample%20powershell%20script%22%20%23should%20look%20like%20sample%20below%3A%0Ahttps%3A%2F%2Fgraph.microsoft.com%2Fv1.0%2Fsites%2Fspotenant.sharepoint.com%2Cdf6ba610-b132-4fc7-0000-000000000000%2Ce0dbcdc6-0637-4246-0000-000000000000%2Fdrive%2Froot%2Fdelta%3Ftoken%3DMzslMjM0OyUyMzE7Mzs3NDlhZjc4NC0zOWU0LTRlOTEtYmJkNy0wNzI5MjAxNTNlMGY7NjM3MzM2NDU1MzMyNDcwMDAwOzMxOTY4OTE4MjslMjM7JTIzOyUyMzA%22%0A%0A%24deltaResult%20%3D%20(Invoke-RestMethod%20-Method%20Get%20-Headers%20%24requestheader%20-Uri%20%24deltaUri)%0A%0AWrite-Host%20%24deltaResult.value%0AWrite-Host%0A%0AWrite-Host%20%22DONE%20at%22%20(Get-Date).ToString()%20-f%20Green%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-TEASER%20id%3D%22lingo-teaser-1741127%22%20slang%3D%22en-US%22%3E%3CP%3EBest%20practices%20for%20discovering%20files%20and%20detecting%20changes%20at%20scale%20is%20documented%20below%3A%3CBR%20%2F%3E%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fonedrive%2Fdeveloper%2Frest-api%2Fconcepts%2Fscan-guidance%3Fview%3Dodsp-graph-online%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%20target%3D%22_blank%22%3Ehttps%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fonedrive%2Fdeveloper%2Frest-api%2Fconcepts%2Fscan-guidance%3Fview%3Dodsp-graph-online%3C%2FA%3E%26nbsp%3Bor%26nbsp%3Baka.ms%2Fscanguidance%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%3C%2FLINGO-TEASER%3E%3CLINGO-LABS%20id%3D%22lingo-labs-1741127%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3EDeveloper%20Support%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E
Microsoft

Delta is, by default, a user-scoped API to drive sync-like behavior. It scopes its results down to the set of changes which are definitely impactful to the caller. It filters out changes which it knows are irrelevant to the caller. When the API cannot definitely determine relevance cheaply, e.g. when it needs to make a full permission enumeration to verify, it will include the result, even though it might not be relevant to the caller.

 

Delta attempts to scope permission-based changes to those relevant to the caller. If the caller's access wasn't altered by the permission change, the item may not be included in the delta results.

 

Clients which are trying to enumerate all permission changes should make sure the follow the recommendations in aka.ms/scanguidance. Namely, there are specific authentication requirements and specific Prefer headers that need to be provided, and failure to do so will result in permission changes being scoped down.

 

The only way to receive the complete set of changes is to use app-only authentication with the Sites.FullControl.All scope and pass header "Prefer"="deltashowsharingchanges,hierarchicalsharing".

 

Steps:

1] Create an App in AAD with Sites.FullControl.All Application permission, see screen shot below:

 

SPDev_Support_0-1601681126806.png


2] Sample powershell script to generate the Access token and the delta token link:

 

 

<#
Code Example Disclaimer:
Sample Code is provided for the purpose of illustration only and is not intended to be used in a production environment.
THIS SAMPLE CODE AND ANY RELATED INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
We grant You a nonexclusive, royalty-free right to use and modify the Sample Code and to reproduce and distribute the object
code form of the Sample Code, provided that. You agree: (i) to not use Our name, logo, or trademarks to market Your software
product in which the Sample Code is embedded; (ii) to include a valid copyright notice on Your software product in which the
Sample Code is embedded; and (iii) to indemnify, hold harmless, and defend Us and Our suppliers from and against any claims or
lawsuits, including attorneys fees, that arise or result from the use or distribution of the Sample Code.
#>

cls

$host.Runspace.ThreadOptions = "ReuseThread"

Write-Host "STARTED at" (Get-Date).ToString() -f Green

$ClientID = "fa9737d5-5a3e-4fab-0000-000000000000"
$ClientSecret = "1JOe:M8HBBUz-0000000000000000000"
$scope= "https://graph.microsoft.com/.default"
$POSTURI =  "https://login.microsoftonline.com/d6f932a7-5f74-0000-0000-000000000000/oauth2/v2.0/token"

$body = @{grant_type="client_credentials";client_id=$ClientID;client_secret=$ClientSecret;scope=$scope}

$oauth = Invoke-RestMethod -Method Post -Uri $POSTURI -Body $body

$graphAccessToken = $oauth.access_token

Write-Host "Access token: $($graphAccessToken)"

$requestHeader = @{

  "Authorization" = "Bearer $graphAccessToken"
  "Content-Type" = "application/json"
  "Prefer" = "deltashowsharingchanges,hierarchicalsharing,deltatraversepermissiongaps,deltashowremovedasdeleted"
}

$Uri = "https://graph.microsoft.com/v1.0/sites/spotenant.sharepoint.com,df6ba610-b132-0000-0000-000000000000,e0dbcdc6-0637-4246-0000-000000000000/drive/root/delta?latest" 

$Result = (Invoke-RestMethod -Method Get -Headers $requestheader -Uri $Uri)

$deltaUri = $Result.'@odata.deltaLink'

Write-Host $deltaUri
Write-Host "DONE at" (Get-Date).ToString() -f Green

 

 

 

3] Copy the Access token and the deltaUri value output from the above script and use them in the following sample powershell script to retrieve the complete set of permission changes:

 

 

<#
Code Example Disclaimer:
Sample Code is provided for the purpose of illustration only and is not intended to be used in a production environment.
THIS SAMPLE CODE AND ANY RELATED INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
We grant You a nonexclusive, royalty-free right to use and modify the Sample Code and to reproduce and distribute the object
code form of the Sample Code, provided that. You agree: (i) to not use Our name, logo, or trademarks to market Your software
product in which the Sample Code is embedded; (ii) to include a valid copyright notice on Your software product in which the
Sample Code is embedded; and (iii) to indemnify, hold harmless, and defend Us and Our suppliers from and against any claims or
lawsuits, including attorneys fees, that arise or result from the use or distribution of the Sample Code.
#>

cls

$host.Runspace.ThreadOptions = "ReuseThread"

Write-Host "STARTED at" (Get-Date).ToString() -f Green

$graphAccessToken = "copied from output of above sample powershell script"

$requestHeader = @{
  "Authorization" = "Bearer $graphAccessToken"
  "Content-Type" = "application/json"
  "Prefer" = "deltashowsharingchanges,hierarchicalsharing"
}

Write-Host

$deltaUri = "copied from output of above sample powershell script" #should look like sample below:
https://graph.microsoft.com/v1.0/sites/spotenant.sharepoint.com,df6ba610-b132-4fc7-0000-000000000000,e0dbcdc6-0637-4246-0000-000000000000/drive/root/delta?token=MzslMjM0OyUyMzE7Mzs3NDlhZjc4NC0zOWU0LTRlOTEtYmJkNy0wNzI5MjAxNTNlMGY7NjM3MzM2NDU1MzMyNDcwMDAwOzMxOTY4OTE4MjslMjM7JTIzOyUyMzA"

$deltaResult = (Invoke-RestMethod -Method Get -Headers $requestheader -Uri $deltaUri)

Write-Host $deltaResult.value
Write-Host

Write-Host "DONE at" (Get-Date).ToString() -f Green