Authenticate SPFx Solutions with MSAL2: Part 1 (Introduction)

Best Practices SharePoint Online SPFx Development Microsoft 365 Security Software Engineering

SPFx 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:

  1. using the AadHttpClient class to call any API secured by Entra ID
  2. 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:
    1. SPFx package includes a manifest with requested permissions
    2. 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
  • Request only the necessary API permissions:
    • For basic functionality, Microsoft Graph User.Read is sufficient
    • Add any additional permissions your application specifically requires

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):

Data Flow

Authentication Flow

Props

Configuration

Props

Auth Context

Uses

Calls

Returns

Stored in

Uses

Consumes

Provides

Enables

SPFxMsalAuthDemoWebPart

SpFxMsalAuthDemo

AuthenticationContextProvider

GraphDataDisplay

PublicClientApplication

Microsoft Identity Platform

Access Token

httpClient

Auth Context

accessToken

API Call to Graph

Read more about the concrete implementation details: Authenticate SPFx Solutions with MSAL2: Part 2 (Implementation).

#BishopTells