We are introducing a set of changes to the way API permissions are managed in SharePoint Online by Tenant Administrators, which should be noted in the context of SharePoint Framework (SPFx) permission grants in the Microsoft Entra ID.
Previously SharePoint Framework solutions permission grants were done against an application called “SharePoint Online Client Extensibility Web Application Principal“, which was automatically created for the customer tenants. That was used as the “identity” of the application that presented itself to get tokens to access APIs like Microsoft Graph or other third party APIs.
Starting from the second week of March 2025, we are beginning to transition to the “SharePoint Online Web Client Extensibility” application principal to be used for SPFx permission management. As the process will take time, if you are not using the API access page for managing permission request you will have to continue to use the existing process you have to keep permissions in sync between the “SharePoint Online Web Client Extensibility” and “SharePoint Online Client Extensibility Web Application Principal” object in Entra ID. We will share an update to this blogpost once the rollout has been completed and the “SharePoint Online Client Extensibility Web Application Principal” object is no longer used.
All previously granted permissions have been automatically copied over which means that the existing SharePoint Framework applications continue to work without any required changes.
We have also updated the API Access Page in SharePoint Online Tenant Administration now displays a set of additional permissions that have been automatically pre-authorized by Microsoft. Those permissions are required for SharePoint Online to function properly. Tenant Administrators can remove those permissions (and add them back via the API Access page), but by doing that they might compromise some of the out of the box functionalities provided by SharePoint. Previously provisioned “SharePoint Online Client Extensibility Web Application Principal” application registration will not be automatically deleted and will remain as unused application registration in any tenant where it was previously created.
Why is this change done?
We introduced this change to provide the following benefits:
- better performance: with a single application we are using a faster path for getting the access tokens and you have shared access tokens with 1st party code (the same token is used by both 1st and 3rd parties)
- better reliability: we ensure the state of the application principal at app boot.
- more governance: as an administrator, you can now control the set of permissions that Microsoft pre-authorized to the application principal. Note however that removing default permissions will affect out of the box functionalities.
PowerShell to grant permissions
As you no longer can grant permissions directly from the Microsoft Entra ID user interface, we also have released an example PowerShell script that can be used in scenarios were you want to manage SharePoint Framework permissions outside of SharePoint Online Tenant Administration user interface.
You can find reference PowerShell script below :
<#
.SYNOPSIS
This cmdlet privovides a way for developer and system administrators to add permissions to AAD protected APIs for SharePoint Framework custom code.
.PARAMETER appID
the ID of the app to set permissions for
.PARAMETER scope
the scope of the permission request to add
.EXAMPLE
AddSPFxPermissions -appID "00000003-0000-0000-c000-000000000000" -scope "Sites.Read.All"
.NOTES
requires Graph SDK to be installed. Follow documentation here: https://learn.microsoft.com/en-us/powershell/microsoftgraph/installation?view=graph-powershell-1.0
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string] $appID,
[Parameter(Mandatory=$true)]
[string] $scope
)
$sPFxAppID = "08e18876-6177-487e-b8b5-cf950c1e598c"
$objectGrant = $null
connect-MgGraph -scopes "Application.ReadWrite.All", "Directory.ReadWrite.All" -NoWelcome
try{
#Get the SPFx Service Principal
$sPFxSP = Get-MgServicePrincipal -Filter "appid eq '$spfxAppID'" -ErrorAction Stop
#get the endpoint service princpal (required to identify the object ID)
$resourceSP = Get-MgServicePrincipal -Filter "appid eq '$appID'" -ErrorAction Stop
#check if some scopes have been already added for the endpoint
$oGrants = Get-MgServicePrincipalOauth2PermissionGrant -ServicePrincipalId $sPFxSP.Id -ErrorAction Stop
foreach ($item in $oGrants)
{
if( $item.ResourceId -eq $resourceSP.Id)
{
$objectGrant = $item
break
}
}
#if $objectGrant is not null, we check if the scope already exists there
if ($null -ne $objectGrant)
{
if ($objectGrant.Scope | Select-String $scope -Quiet ){
throw "Scope has already been granted"
}
#The scope was not added, added it to the $objectGrant and update it
$objectGrant.Scope += " $scope"
Update-MgOauth2PermissionGrant -OAuth2PermissionGrantId $objectGrant.Id -Scope $objectGrant.Scope -ErrorAction Stop | Out-Null
}
#otherwise, we just create the new object witht the scope
else{
$params = @{
"clientId" = $sPFxSP.id
"ConsentType" = "AllPrincipals"
"ResourceId" = $resourceSP.id
"scope" = $scope
}
New-MgOauth2PermissionGrant -BodyParameter $params -ErrorAction Stop | Out-Null
}
Write-Host "Permissions set for SPFx app with ID $appID"
}
catch{
Write-Host "the following error occurred: $_.Exception" -ForegroundColor Red
}
finally{
Disconnect-MgGraph
Write-Host "Command completed."
}
I’d like to report that I’m still seeing inconsistencies across several tenants (I currently manage three), which makes it difficult to understand where we stand in the rollout process. This is somewhat frustrating, especially given the lack of recent updates or clarification on the status of the deployment.
Production tenant (created in 2019)
✅ OK: When accessing the Graph API using msGraphClientFactory in an SPFx web part, it now uses a token for "SharePoint Online Web Client Extensibility".
❌ Not OK: The API Access page in the SharePoint Admin Center still uses the old view and does not show the column "Pre-authorized...
Is there any update?
Today I've tried to add the PnP Modern Search package to a tenant. It requested the MS Graph permissions in the SharePoint Admin Center API Access, but in the permissions list, Files.Read.All was missing, since it was pre-authorized by Microsoft.
A Global Administrator did the approvals.
When testing the PnP Modern Search webpart, I get:
Access to OneDriveFile in Graph API requires the following permissions: Files.Read.All or Sites.Read.All or Files.ReadWrite.All or Sites.ReadWrite.All. However, the application only has the following permissions granted: Acronym.Read.All, Bookmark.Read.All, ChannelMessage.Read.All, Chat.Read, Chat.ReadWrite, ExternalItem.Read.All, Mail.Read
The JWT token of the PnP Modern Search Searchbox webpart shows that the...
@Alex, thank you very much for your feedback. What you are experiencing is not supposed to happen but it is, instead, because of a bug we have discovered and fixing as we speak where the initial permissions are not get kept in sync.
As an immediate workaround what you can do is to remove the pre-authorized permission you need e.g. "Files.Read.All" and then restore it back. That will ensure the permission is in sync on both objects.
Again: that is not what should be done and I really apologies for the issue you and other customers are experiencing. Fix is on its...
Hey @Alex, we are talking about sometime around beginning of May.
@Luca, our client is asking – is there a high level timeline for the fix?
@Luca, thank you for sharing, it’s good to know a fix is on its way.
Note: The script mentioned above doesn’t work correctly unless “| Out-Null” is being removed from the lines where “$sPFxSP” and “$resourceSP” are assigned.
I also found this to be the case.
I would like to report an issue encountered following the transition to the "SharePoint Online Web Client Extensibility" as the principal for managing SPFx permissions. In several Azure environments, I have configured Function Apps with authentication, limiting access to calls coming from the “SharePoint Online Client Extensibility Web Application Principal” of SharePoint. However, a few days ago, on a customer’s tenant, we noticed that only certain VIP users, who previously had no access issues, were now receiving "not authorized" errors.
Upon analyzing the authentication bearer token, we found that the calls from these users were coming from the new "SharePoint Online...
Ciao Vincenzo,
I cannot comment on your code as I don't have access to it. However, if you have a reference to the previous principal name, you will have to change to the one that is mentioned in the script that is part of this articles.
Also in regards of your "Additionally, an important point is that with the “SharePoint Online Client Extensibility Web Application Principal,” it was possible to manually manage permissions directly from portal.azure.com, while with the new principal this no longer seems to be possible. It would be helpful to receive clarification on how to manage permissions with the...
I noticed the same in Azure API management as that started to give suddenly 401. When I checked the claims from the bearer token I noticed that the appid had changed where the policy validates the inbound request.
This change seems to now break the special folder setup for any custom apps. This creates new folder to users OneDrive under the Apps called “SharePoint Online Web Client Extensibility”, but the configurations we might have saved for users are in the old “SharePoint Online Client Extensibility Web Application Principal”. This not very nice that this kind of change happens breaks these.
Kalle, apologize for introducing such change in a way that disrupted your solution. I guarantee you that it was not our intention. One thing to consider: one of the out of the box scopes available in all tenants is now “files.read.all”. That means that (and yes, I understand that requires a change in your codebase) you can read the configuration in the previous folder and apply that to the new one.
Regarding the code provided (PowerShell). I do not know what the following constant is keeping? Suppose that it has to be updated for a use in my tenant but not sure where to get it.
This ID is the same for every tenant. It’s a First Party application by Microsoft (verify here: https://learn.microsoft.com/en-us/troubleshoot/entra/entra-id/governance/verify-first-party-apps-sign-in).
The service principal in your tenant (that the script is looking for) is found by filtering on this ‘appid’ property. It later uses the ‘Id’ property of the service principal to find the Oauth2PermissionGrants. This ‘Id’ property is unique for your tenant.
I noticed that the API access page is no longer working if I try to enable a custom API. The first time I noticed it was on Friday March 7. Is it possible that this is related to the changes described in this article?
If I try to enable the API I receive an error message: "Access can't be approved because you didn't accept the requested permissions.".Read more
In the network trace I noticed that it uses the Graph API to get the app from Entra ID, but since I has never been approved first, it always returns an empty array. (https://graph.microsoft.com/beta/servicePrincipals/?$filter=appId%20eq%20%27[AppID]%27)
A fix for this has been checked in and will be available in production environments by end of next week. If you want to unblock yourself earlier then use a Graph call to create the service principal manually. The AppId is the one that we keep on trying to load as you’ve explained in your post Florian
POST https://graph.microsoft.com/v1.0/servicePrincipals
{
“appId”: “[AppID]”
}
Florian, thanks for your feedback.
That should not happen and it is tangential to this change. if the issue is still happening, can you please rise an issue in GitHub here: https://github.com/SharePoint/sp-dev-docs/issues?
Thank you.
Is there any value being added by this limitation in Entra ID and forcing PowerShell to update permissions? For example, does it get us closer to having app specific permissions while allowing SPFx to handle the token acquisition?
Hello Troy, thanks for your feedback,
the fact you cannot use Entra ID to manage permissions anymore is a consequence of transitioning from an Application Principal to a Service Principal, and Entra ID doesn't provide an UX in the Portal for permission management at Service Principal level.
In terms of "why" we made that change, those are the benefits:
* Better performance: with a single application we are using a faster path for getting the access tokens and you have shared access tokens with 1st party code (the same token is used by both 1st and 3rd parties)
* better reliability:...