This post outlines how to limit access to an Azure Functions App so that only tenant users can access it, and how to then consume this function from an SPFx app in SharePoint.
Updated: Use SharePoint Online Web Client Extensibility instead of SharePoint Online Client Extensibility Web Application Principal
Preparations
- Your functions should use AuthorizationLevel.Anonymous since the underlying App Service will be taking care of authentication.
- Enable CORS on the Function App in Azure and allow the SharePoint domain.
On the App Registrations blade in Azure Entra ID, find SharePoint Online Client Extensibility Web Application Principal and copy the “Application (Client) ID”.- On Enterprise Applications blade in Azure Entra ID, find SharePoint Online Web Client Extensibility and copy the (Client) ID (should be: 08e18876-6177-487e-b8b5-cf950c1e598c).
Secure the Functions App in Azure
- On the Authentication blade, select Add Identity Provider.
- Choose Microsoft.
- Under Client application requirement, select Allow requests from specific client applications and add the Client ID for the SharePoint app you copied above.
- Other settings can be left pretty much as is.
- When you click Add a new Entra ID App is created.
- Copy the App (Client) ID and App Display Name of the app.
Optional: Azure created some settings that we will not use. These can be removed to avoid confusion:
- On the Environment settings blade in the Function App, remove the MICROSOFT_PROVIDER_AUTHENTICATION_SECRET entry.
- In Entra ID, go to App Registrations and find the newly created app. On the Authentication blade, remove the “Web” platform. On the Certificates & Secrets blade, remove the “Client Secret”.
Setup SPFx Permissions
- Open package-solution.json in your SPFx solution. Add the following to the solution section:
1 2 3 4 5 6 7 8 9 10 |
"webApiPermissionRequests": [ { "resource": "Windows Azure Active Directory", "scope": "User.Read" }, { "resource": "[DISPLAY NAME OF THE ENTRA ID APP]", "scope": "user_impersonation" } ] |
- Build your solution ( gulp clean && gulp bundle --ship && gulp package-solution --ship ). A SharePoint package (.sppkg) file is created in the SharePoint/solution folder.
- Open your tenant app catalog and upload and upload the package. Enable it when asked.
- When done, click Go to API access page. Find your app and Approve it.
Note: At this point you can remove your app from the app catalog while you continue developing it locally.
Call the function
Finally, to call the function from your SPFx code, use AadHttpClient :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import { AadHttpClient, HttpClientResponse } from '@microsoft/sp-http'; ... this.context.aadHttpClientFactory .getClient('api://[CLIENT ID OF YOUR ENTRA ID APP]') .then((client: AadHttpClient): void => { client.get('https://[FUNCION-APP-NAME].azurewebsites.net/api/[FUNCTION NAME]', AadHttpClient.configurations.v1) .then((response: HttpClientResponse): Promise<any> => { return response.json(); }) .then((result: any): void => { console.log("✅", result); }, (err: any): void => { console.log("❌", err) }); }); |
Learnings
The normal authentication flow is to redirect the user to a login prompt. If each SPFx web parts used this flow it would not be a good user experience. Instead, SharePoint has a special app, the “SharePoint Online Web Client Extensibility”. This app is pre-authenticated and we can use it to make secure. So when implementing authentication in our own APIs we need to allow the SharePoint app instead of our own.
Amazing… I struggled with this for 8 hours today. Explicit allowing requests from only client id 08e18876-6177-487e-b8b5-cf950c1e598c and publishing as anonymous is critical… this is so poorly documented anywhere. Thanks a lot.
I used this article a few months ago to set up my spfx to consume a Microsoft authentication secured Azure Function. Thanks.
Today I enabled managed identity in the Azure Function and it stopped working. I wonder if you have any inside as to how an spfx can connect to an Azure Function that has a managed identity