Beware of Declarative Permissions in SharePoint Framework Projects

Developers can declare permissions in SharePoint Framework projects, but it isn't a good idea. In this article I explain why and suggest a better approach.

By Last Updated: July 14, 2024 7 minutes read

In the SharePoint Framework (SPFx) v1.6.0 release, Microsoft introduced a capability that allowed developers to call Microsoft Entra ID (formerly Azure AD) secured APIs & endpoints. These calls are made through a proxy Microsoft Entra ID application that’s available in all SharePoint Online tenants.

How does it work?

Microsoft created a special Entra ID application in every SharePoint Online (SPO) tenant. A tenant admin grants this application permissions to a specific Entra ID secured endpoint. You then use the AadHttpClient API to ask SPO to provide you with an OAuth access token to call the specified endpoint. SPO will authenticate and verify your SPO tenant has been granted this permission to the specified endpoint prior to returning the access token. You can then use this access token to directly call the target endpoint straight from your SPFx component.

You can learn more about this from the SPFx docs (Connect to APIs secured with Entra ID using the AadHttpClient) and in my course: Mastering the SharePoint Framework.

Make Sure you Understand How SPO Is Granted Permissions to the Endpoint

One very important aspect to this capability is that when you grant your SPO tenant permission to a specified endpoint, you are doing so for your entire SharePoint Online tenant. I’m being very specific in my wording there. Once your tenant has been granted permission to a specified endpoint, any custom code or user can request an access token to call the endpoint.

This includes any client-side code deployed as an SPFx component, random JavaScript on the page or even code you run from the browser’s developer tools JavaScript console.

The reason is simple: there’s simply no way for the server-side code to determine what code triggered the request from the client for the access token. It can’t tell it came from the console, a specific web part or a content editor web part.

In addition, permissions are not tied to any specific SPFx component. I can deploy & install a SPFx component that requires permissions without granting the permissions. In this case, when the component requests the access token, SPFx will throw an error. Furthermore, uninstalling the SPFx component will not remove any prior permission grants.

Another key point here: SPO permission grants are not associated with SPFx components: they are only associated with the SPO tenant.

Granting SPO permissions to the API

So how do you do you grant permissions to the special SPO Entra ID application? There are three options:

  • declaratively request within an SPFx component & manually approve in the SharePoint Admin Center
  • explicitly via PowerShell using the command line if you’re on Windows
  • explicitly via CLI for Microsoft 365 using the command line regardless of the platform you’re on

The documentation page I mentioned above, Connect to APIs secured with Entra ID using the AadHttpClient, does a really good job explaining the different options and demonstrating each option.

Recommendation: Avoid the Declarative Option to Grant SPO Entra ID Permissions

Most of the demos you see use the declarative option that I mentioned above.

package-solution.json - webApiPermissionRequests element

package-solution.json - webApiPermissionRequests element

In this option, you specify the resource & permission your custom SPFx component needs in the component’s package-solution.json file. When the component is deployed, the admin is displayed a message informing them they need to go approve the permission in the SharePoint Online Admin Center.

Package deployment prompt for additional steps required

Package deployment prompt for additional steps required

API Management page in the Microsoft 365 Portal

API Management page in the Microsoft 365 Portal

From here, the tenant admin can approve or reject the permission. This demos great, but there are a bunch of reasons why I don’t like this:

  • Implies permission is tied to the SPFx component: When you look at the permission request, it shows the SPFx package that requested it. This sort of implies that this permission request is associated with the SPFx component. All it says is that this is the component that requested it… but it can be easily confused.

    API permission request - Approve/Reject dialog

    API permission request - Approve/Reject dialog

    But it isn’t! The permission is granted to the special Entra ID application for SharePoint Online. This implementation in the SharePoint Admin Center is misleading as administrators frequently think that the permission is granted to an application when in reality, it’s granted to the entire tenant!

  • Makes the API admin list messy: Let’s say you’ve already granted your SPO tenant the Mail.Read permission to the Microsoft Graph. If you deploy another application that has the same permission request, it will show up again as a pending permission request even though your SPO tenant has already been granted the permission. If you try to approve the permission, you’ll see an error saying it’s already approved… that’s confusing!

    Don't be fooled by duplicate permission requests

    Don't be fooled by duplicate permission requests

    What’s even worse is that if you have multiple permissions requested in one SPFx package, they are all grouped together. So… let’s say you had User.Read in addition to Mail.Read for the Microsoft Graph in the list of permissions. If one was already approved but the other wasn’t, you would get another error… even though you’re just trying to add one permission to the list.

    Don't be fooled by duplicate permission requests

    Don't be fooled by duplicate permission requests

    What do you do now? You can reject or ignore the duplicate permission request because the existing approved request is all you need will serve the purpose, but that’s not a great user experience from my point of view.

While the declarative options work just fine functionally, I am not a fan of it at all. From my point of view, the API management page in the SharePoint Admin center is broken or the design is flawed in how it works. If a permission is already granted to my tenant, granting it again should not throw an error or block me from granting other permission at the same time. But that’s just my opinion.

For that reason, and the others I’ve outlined above, I recommend people avoid this option for granting their SPO tenant permissions to endpoints and services secured with Entra ID.

Recommendation: Grant SPO Entra ID Permissions with PowerShell or the CLI for Microsoft 365

Instead, I recommend you use either SharePoint Online PowerShell or the CLI for Microsoft 365 to grant your permissions. Which one is totally up to you… I prefer the CLI for Microsoft 365, but it doesn’t matter what you use.

With the command line option, you can list, request, grant and reject permissions. This can be done independently of the deployment of the component.

When I create an SPFx component that calls an Entra ID-secured API, I check for the HTTP status code 401 which tells me I’m not authorized to call the endpoint. When I see it, my web part displays a message showing the PowerShell / CLI for Microsoft 365 command to execute to grant the permission. Anyone can see it, but only a tenant admin can execute it.

Using the CLI for Microsoft 365

To get a list of all the permissions granted to your tenant, use the following command:

m365 login
m365 spo serviceprincipal grant list

Then, to add a permission to the SharePoint Online Entra ID app, such as the Mail.Read Microsoft Graph permission, use the grant add command:

m365 spo serviceprincipal grant add --resource 'Microsoft Graph' --scope 'Mail.Read'

If you need to remove the permission, you can use the grant revoke command:

m365 spo serviceprincipal grant list
# review the response to find the grant you want to remove and get it's ID

m365 spo serviceprincipal grant revoke --id 50NAzUm3C0K9B6p8ORLtIsQccg4rMERGvFGRtBsk2fA

You can also use the permissionrequest command to list, approve, and deny permission requests that were submitted using the declarative approach:

m365 spo serviceprincipal permissionrequest list
# get the ID of the request...

# ... to approve it...
m365 spo serviceprincipal permissionrequest approve --id 4dc4c043-25ee-40f2-81d3-b3bf63da7538

# ... or reject it it...
m365 spo serviceprincipal permissionrequest deny --id 4dc4c043-25ee-40f2-81d3-b3bf63da7538

Using the SharePoint Online PowerShell

To get a list of all the permissions granted to your tenant, use the following command:

Connect-SPOService -Url https://voitanos-admin.sharepoint.com
Get-SPOTenantServicePrincipalPermissionGrants

Then, to add a permission to the SharePoint Online Entra ID app, such as the Mail.Read Microsoft Graph permission, use the Approve-SPOTenantServicePrincipalPermissionGrant cmdlet:

Approve-SPOTenantServicePrincipalPermissionGrant --Resource 'Microsoft Graph' --Scope 'Mail.Read'

If you need to remove the permission, you can use the grant revoke command:

Get-SPOTenantServicePrincipalPermissionGrants
# review the response to find the grant you want to remove and get it's ID

Revoke-SPOTenantServicePrincipalPermission --ObjectId 50NAzUm3C0K9B6p8ORLtIsQccg4rMERGvFGRtBsk2fA

You can also use the Get-SPOTenantServicePrincipalPermissionRequests cmdlet to list, approve, and deny permission requests that were submitted using the declarative approach:

Get-SPOTenantServicePrincipalPermissionRequests
# get the ID of the request...

# ... to approve it...
Approve-SPOTenantServicePrincipalPermissionRequest --RequestId 4dc4c043-25ee-40f2-81d3-b3bf63da7538

# ... or reject it it...
Deny-SPOTenantServicePrincipalPermissionRequest --RequestId 4dc4c043-25ee-40f2-81d3-b3bf63da7538

Conclusion

I encourage you to consider how you request and declare permissions in SharePoint Online for your SharePoint Framework apps and evaluate the experience when you are using this powerful capability in SPFx.