PowerShell: Removing Web API Permissions for SPFx Solutions used by EntraId SharePoint Online Web Client Extensibility
The script checks the ‘SharePoint Online Web Client Extensibility’ Principal within Entra ID for the actual assigned permissions as the SPFx solutions requests are all be added to that single shared permission group.
As hilghlighted by “Wes Hackett”:
I’ve personally seen plenty of tenants with Mailbox permissions with no corresponding solutions live in the app catalogs. Early SPFx doc examples encouraged the use of MS Graph into Mailbox permissions in one of the how to learn samples, older tenants sometimes have this breadcrumb left behind.
When SPFx solutions are uninstalled, these Web API permissions remain in place, potentially allowing other apps to access these APIs without admin consent, posing security risks.
SharePoint Online Client Extensibility Web Application Principal
The app registrations used by SPFx when making calls to Entra ID secured APIs are created automatically, and permissions are granted as described below. In SPFx code, Entra ID permission requests can be made by adding a webApiPermissionRequests element inside the config/package-solution.json file.
"webApiPermissionRequests": [
{
"resource": "Microsoft Graph",
"scope": "User.Read.All"
},
{
"resource": "Microsoft Graph",
"scope": "User.ReadBasic.All"
},
{
"resource": "Microsoft Graph",
"scope": "Sites.Read.All"
},
{
"resource": "Microsoft Graph",
"scope": "profile"
}
]
Permissions can be added either manually or through scripting. For instructions on adding permissions via the UI, refer to Granting API permissions requests for SPFx. To manage these permissions using PowerShell, see Managing Service Principal Permission Requests using PowerShell.
Changes made in the API access page affect the permissions associated with the SharePoint Online Client Extensibility Web Application Principal
app registration and apply to all SPFx solutions in the tenant.
Refer to SharePoint solutions as a spyware to understand the security risks,as other apps can use these endpoints without further admin consent.
PowerShell Script
The following PowerShell script audits and removes unused Web API permissions:
param (
[Parameter(Mandatory = $true)]
[string] $domainName,
[Parameter(Mandatory)]
[ValidateSet('Yes','No')]
[string]$deleteUnusedWebApiPermissions
)
$dateTime = (Get-Date).toString("dd-MM-yyyy-hh-mm")
$invocation = (Get-Variable MyInvocation).Value
$directorypath = Split-Path $invocation.MyCommand.Path
$fileName = "\WebAPIPermissions" + $dateTime + ".csv"
$OutPutView = $directorypath + $fileName
$adminUrl = "https://$domainName-admin.sharepoint.com/"
<#WARNING: Connecting with -Interactive uses the PnP Management Shell multi-tenant App Id for authentication. It is strongly recommended to register your own EntraID App for authentication. See the documentation for Register-PnPEntraIDApp.#>
Connect-PnPOnline -Url $adminUrl -Interactive -WarningAction SilentlyContinue
$permissionsGrants = Get-PnPTenantServicePrincipalPermissionGrants
# Retrieve which SPFx solutions have WebApiPermission scopes granted
$RestMethodUrl = '/_api/web/lists/getbytitle(''Apps%20for%20SharePoint'')/items?$select=Title,WebApiPermissionScopesNote'
$tenantAppCatalogUrl = Get-PnPTenantAppCatalogUrl
$appsDetails = @()
Connect-PnPOnline $tenantAppCatalogUrl -Interactive -WarningAction SilentlyContinue
$appCatConnection = Get-PnPConnection
$apps = (Invoke-PnPSPRestMethod -Url $RestMethodUrl -Method Get -Connection $appCatConnection).Value
#export details of apps
$apps| foreach-object{
$app = $_
$app | Add-Member -MemberType NoteProperty -name "Site Url" -value $tenantAppCatalogUrl
$appsDetails += $app
}
Get-PnPSiteCollectionAppCatalog -ExcludeDeletedSites | ForEach-Object {
write-host "Processing Site:" $_.AbsoluteUrl -f Yellow
$Site = Get-PnPTenantSite $_.AbsoluteUrl -Connection $adminConnection
<#WARNING: Connecting with -Interactive uses the PnP Management Shell multi-tenant App Id for authentication. It is strongly recommended to register your own EntraID App for authentication. See the documentation for Register-PnPEntraIDApp.#>
Connect-PnPOnline -Url $Site.url -Interactive -WarningAction SilentlyContinue
$siteConnection = Get-PnPConnection
try{
$apps = (Invoke-PnPSPRestMethod -Url $RestMethodUrl -Method Get -Connection $siteConnection).Value
$apps| foreach-object{
$app = $_
$app | Add-Member -MemberType NoteProperty -name "Site Url" -value $Site.url
$appsDetails += $app
}
}
catch{
write-host -f Red $_.Exception.Message
}
}
$permissions = $permissionsGrants | foreach-object {
$permissionGrant = $_
$app = $appsDetails | where-object { $_.WebApiPermissionScopesNote -match "$($permissionGrant.Resource), $($permissionGrant.Scope)" }
if($DeleteUnusedWebApiPermissions -eq "Yes"){
if(!$app){
Revoke-PnPTenantServicePrincipalPermission -Scope $permissionGrant.Scope -Resource $permissionGrant.Resource -Force -WarningAction SilentlyContinue
Write-Host "Deleted permission grant for $($permissionGrant.Resource), $($permissionGrant.Scope)" -ForegroundColor Yellow
}
}
if($DeleteUnusedWebApiPermissions -eq "No" -or $app){
[PSCustomObject]@{
Permission = "$($permissionGrant.Resource), $($permissionGrant.Scope)"
UsedIn_Solution = $app ? "$($app.'Site Url'), $($app.Title)" -join ";" : "Not used"
ResourceId = $permissionGrant.ResourceId
ServicePrincipal = $permissionGrant.ServicePrincipalDisplayName
}
}
}
$permissions | Export-CSV -Path $OutPutView -NoTypeInformation
Example Outputs
When all API permissions are used by more than one SPFx solution:
After the SPFx PnP Modern Search - Search Web Parts - v4
is uninstalled, the API permissions granted to it still persist:
If deleteUnusedWebApiPermissions
flag is set to ‘Yes’:
The report shows retained API permissions used:
From the UI , only those API permissions used are shown as approved:
MsGraphClient versus AadHttpClient
For more information on why AadHttpClient is the preferred option, refer to the slides M365 Development Security – From full trust to Zero Trust by Markus Moeller. Using AadHttpClient with an Azure Function shifts permissions to “own Entra ID,” which can enhance security. However, this approach may incur additional costs and setup requirements, and may not be suitable for organizations that are not yet mature in Azure development.
Conclusion
Managing Web API permissions for SPFx solutions is essential for maintaining a secure SharePoint Online environment. The provided PowerShell script helps audit and remove unused API permissions, reducing the risk of unauthorized access. However, always ensure to review permissions before revoking them to avoid disrupting any active solutions. Also consider using AadHttpClient for a more secure option.
References
SharePoint solutions as a spyware
Granting API permissions requests for SPFx
Beware of Declarative Permissions in SharePoint Framework Projects