Authenticate SPFx Solutions with MSAL2: Part 1 (Introduction)
Best Practices SharePoint Online SPFx Development Microsoft 365 Security Software EngineeringSPFx solutions and the (missing) «principle of least privilege»
SharePoint Framework (SPFx) solutions often need to access protected resources such as Microsoft Graph API or custom APIs. Although SPFx provides built-in authentication capabilities, certain scenarios require more granular control over the authentication process and permissions. In certain situations, it will become necessary to implement your own authentication within your SPFx webpart or extension: by making use of the Microsoft Authentication Library (MSAL) you can gain finer control over the authentication process while following the «principle of least privilege» (PoLP).
Note
If you are more interested in the principle of least privilege and what permissions could look like in M365 solutions, you can read this article:Scopes and permissions in the Microsoft identity platform
To make it clear from the beginning: unfortunately, the commonly used authentication process provided by SPFx doesn’t really follow a proper PoLP approach. But let’s start at the beginning.
The out-of-the-box Approaches or: the Standard («Built-in») Authentication from any SPFx Solution
By default, SPFx solutions can access Microsoft Graph API and other secured APIs via built-in authentication mechanisms provided by the framework. The implementation of these mechanisms is fairly easy and therefore very convenient.
SharePoint Framework provides two primary ways to authenticate to Entra ID-secured resources:
- using the
AadHttpClient
class to call any API secured by Entra ID - using the
MSGraphClient
class to call the Graph API directly
Using AadHttpClient
The AadHttpClient
class in SPFx allows web parts and extensions to call Entra ID-secured APIs without having to handle authentication details directly. Behind the scenes, it uses the OAuth implicit flow, which brings up some security concerns for modern (web) applications.
Note
Read more about theauthorization code flow with PKCE («No Proof Key for Code Exchange») and why it is a better alternative to the implicit flow: Microsoft identity platform and OAuth 2.0 authorization code flow
As described in the official documentation, this approach works as follows to contact your API (or any official API provided and documented by Microsoft):
import { AadHttpClient, HttpClientResponse } from '@microsoft/sp-http';
// Example of using AadHttpClient
this.context.aadHttpClientFactory
.getClient('api://example.com/app-id') // set your resource or any API provided by Microsoft
.then((client: AadHttpClient): void => {
client
.get('https://api.example.com/resource', AadHttpClient.configurations.v1)
.then(response => {
// Handle response
});
});
The key aspects of this built-in authentication flow are:
- API Permission Registration: The API you want to access must be registered in the SharePoint Admin Center under “API Access”
- Permission Request Process:
- SPFx package includes a manifest with requested permissions
- Package is deployed to the app catalog
- Permission Scope: Permissions are granted at the tenant level and apply to all instances of your SPFx solution
- Token Acquisition: The framework handles token acquisition, renewal, and caching behind the scenes
Using the MSGraphClient
class
Similarly, for calling resources from the Microsoft Graph API specifically, SPFx provides the MSGraphClient
out-of-the-box:
this.context.msGraphClientFactory
.getClient()
.then((client: MSGraphClient): void => {
client
.api('/me') // call any graph route according your needs
.get((error, response) => {
// Handle response
});
});
Limitations of these approaches
While (to be honest: very 😃) convenient, these out-of-the-box approaches have significant limitations:
- Tenant-Wide Permissions: Permissions must be approved by tenant administrators in the SharePoint Admin Center and are granted at the tenant level for ALL SPFx applications 😳
- No Granular Control: It’s impossible to restrict permissions for specific web part instances or extensions – granted permissions can be leveraged by ANY client-side request in the whole tenant!
- Removing a solution doesn’t revoke their (former) permissions: admins have to manually revoke permissions after deleting (if they do so!)
- Limited Customization: You can’t easily use custom authentication flows, policies, or handle specific authentication scenarios
- Permission Bundling: All permissions are bundled together (in Entra’s SharePoint Online Client Extensibility Web Application Principal app registration), making it difficult to follow the principle of least privilege
- Admin Overhead: Requires SharePoint administrators to approve permissions, which can be a bottleneck in large organizations
As «Mr. M365 Development» Andrew Connell noted in discussions about Graph API authentication in SPFx, the built-in approach often leads to excessive permissions being granted, violating the principle of least privilege.
The «proper» approach: Custom Authentication from your SPFx Solution
While the standard («built-in») authentication process is very easy to follow, the custom authentication flow takes far better account of the principle of least privilege.
By implementing MSAL directly (as shown below), you gain really crucial security advantages while maintaining control over your application’s authentication process. And that’s how it works.
Define Your Own App Registration in Microsoft Entra ID
To gain more control, we need to register our own application in Microsoft Entra ID. The key benefit of this approach is that you only request the specific permissions your application needs – rather than making use of «commonly used» permissions how the built-in SPFx authentication flow does.
By making use of the CLI for Microsoft 365 command to create the Entra application, you can register a new application with less effort:
m365 entra app add --name "MSAL AuthN SPFx App" --platform spa --redirectUris "https://{tenant}.sharepoint.com" --apisDelegated "https://graph.microsoft.com/User.Read" --grantAdminConsent
Note
Add any additional permissions that your applicationspecifically requires by specifying the corresponding permissions in the --apisDelegated
parameter.
Alternatively, if you want to take a manual approach (which I wouldn’t 😃), make sure you register your application as follows:
- Create an app registration in the Microsoft Entra admin center (https://entra.microsoft.com/#view/Microsoft_AAD_RegisteredApps)
- Configure it as a Single-page Application (SPA):
- Authentication type: Single-page application (SPA)
- Supported account types: Accounts in this organizational directory only (single tenant)
- Set appropriate redirect URIs:
- Add your SharePoint domain:
https://{tenant}.sharepoint.com
- Add your SharePoint domain:
- Request only the necessary API permissions:
- For basic functionality, Microsoft Graph
User.Read
is sufficient - Add any additional permissions your application specifically requires
- For basic functionality, Microsoft Graph
Once registered, you’ll need these three values from the registered app:
- Application (client) ID to identify your app registration
- Directory (tenant) ID to identify your Microsoft 365 tenant
- Configured redirect URI thandle the authentication response
These values 👆 are used in your SPFx solution with MSAL so that your web part can authenticate itself using your specific application registration – and not using the standard SPFx authorisations!
Implementing MSAL2 Authentication in SPFx
When it comes to implementation, the Microsoft Authentication Library (MSAL2) offers a comprehensive set of APIs for handling authentication and authorization in your SPFx web parts and extensions.
From a architectural perspective, the implementation of MSAL2 in SPFx can be modularized into these components and their interactions – which we will cover in the next parts of this series (see link below):
Read more about the concrete implementation details: Authenticate SPFx Solutions with MSAL2: Part 2 (Implementation).