🚀 DAY 3 OF LAUNCH WEEK:Announcing Bun and vlt Support in Socket.Learn more
Socket
Book a DemoInstallSign in
Socket

@equinor/fusion-framework-module-msal

Package Overview
Dependencies
Maintainers
4
Versions
145
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@equinor/fusion-framework-module-msal

Microsoft Authentication Library (MSAL) integration module for Fusion Framework

Source
npmnpm
Version
6.0.0-next.0
Version published
Weekly downloads
2K
-17.65%
Maintainers
4
Weekly downloads
 
Created
Source

@equinor/fusion-framework-module-msal provides secure Azure AD authentication for browser applications using Microsoft's MSAL (Microsoft Authentication Library). Perfect for web applications, SPAs, and React apps that need to authenticate with Microsoft services.

Version: This package now uses MSAL Browser v4, providing the latest security improvements and features from Microsoft.

Features

  • Single Sign-On (SSO) support for Microsoft Azure AD and Azure AD B2C
  • Token Management with automatic refresh and secure caching
  • Module Hoisting for shared authentication state across application scopes
  • Silent Authentication for seamless user experience
  • Popup & Redirect Flows for different authentication scenarios
  • Zero Configuration with sensible defaults and optional customization
  • MSAL v4 Compatibility with v2 proxy layer for backward compatibility

Quick Start

pnpm add @equinor/fusion-framework-module-msal
import { enableMSAL, initialize, type IMsalProvider } from '@equinor/fusion-framework-module-msal';
import { ModulesConfigurator } from '@equinor/fusion-framework-module';

// 1. Configure the module
const configurator = new ModulesConfigurator();

enableMSAL(configurator, (builder) => {
  builder.setClientConfig({
    auth: {
      clientId: 'your-client-id',
      tenantId: 'your-tenant-id',
      redirectUri: 'https://your-app.com/callback'
    }
  });
  // With requiresAuth=true, the module will attempt automatic login during initialization
  // and await a valid authenticated account before initialization completes
  builder.setRequiresAuth(true);
});

// 2. Initialize the framework (auto-initializes auth provider)
const framework = await initialize(configurator);
const auth: IMsalProvider = framework.auth;

// 3. Optional: Handle authentication redirect manually (auto-called during initialization)
const redirectResult = await auth.handleRedirect();
if (redirectResult?.account) {
  console.log('Authenticated:', redirectResult.account.username);
}

// 4. Use authentication
// Option A: Token acquisition (v4 format - recommended)
const token = await auth.acquireAccessToken({ 
  request: { scopes: ['api://your-app-id/.default'] } 
});

// Option B: Legacy format (still supported via v2 proxy)
const legacyToken = await auth.acquireAccessToken({ 
  scopes: ['api://your-app-id/.default'] 
});

// Option C: Silent authentication with fallback
try {
  const result = await auth.login({ 
    request: { scopes: ['api://your-app-id/.default'] },
    silent: true  // Attempts SSO first
  });
} catch {
  // Fallback to interactive if silent fails
  await auth.login({ 
    request: { scopes: ['api://your-app-id/.default'] },
    behavior: 'popup'
  });
}

[!IMPORTANT] The @equinor/fusion-framework-app enables this package by default, so applications using the app package do not need to enable this module manually.

Configuration

Required Settings

SettingDescriptionRequired
auth.clientIdAzure AD application client ID
auth.tenantIdAzure AD tenant ID
auth.redirectUriAuthentication callback URLOptional

Optional Settings

SettingDescriptionDefault
requiresAuthAuto-authenticate on initializationfalse
versionForce specific MSAL versionLatest

Environment Variables

# Required
AZURE_CLIENT_ID=your-client-id
AZURE_TENANT_ID=your-tenant-id

# Optional
AZURE_REDIRECT_URI=https://your-app.com/callback

API Reference

enableMSAL(configurator, configure?)

Enables the MSAL module in your Fusion Framework application.

Parameters:

  • configurator: IModulesConfigurator - The modules configurator instance
  • configure?: (builder: { setClientConfig, setRequiresAuth }) => void - Optional configuration function

Returns: void

Example:

enableMSAL(configurator, (builder) => {
  builder.setClientConfig({ auth: { clientId: '...', tenantId: '...' } });
  builder.setRequiresAuth(true);
});

Type Definitions

LoginOptions

type LoginOptions = {
  request: PopupRequest | RedirectRequest;  // MSAL request object
  behavior?: 'popup' | 'redirect';          // Auth method (default: 'redirect')
  silent?: boolean;                         // Attempt silent auth first (default: true)
};

LogoutOptions

type LogoutOptions = {
  redirectUri?: string;                     // Redirect after logout
  account?: AccountInfo;                    // Account to logout (defaults to active)
};

AcquireTokenOptions

type AcquireTokenOptions = {
  request: PopupRequest | RedirectRequest;  // MSAL request with scopes
  behavior?: 'popup' | 'redirect';          // Auth method (default: 'redirect')
  silent?: boolean;                         // Attempt silent first (default: true if account available)
};

IMsalProvider

The authentication provider interface available at framework.auth:

interface IMsalProvider {
  // The MSAL PublicClientApplication instance
  readonly client: IMsalClient;
  
  // Current user account information
  readonly account: AccountInfo | null;
  
  // Initialize the MSAL provider
  initialize(): Promise<void>;
  
  // Acquire an access token for the specified scopes
  acquireAccessToken(options: AcquireTokenOptionsLegacy): Promise<string | undefined>;
  
  // Acquire full authentication result
  acquireToken(options: AcquireTokenOptionsLegacy): Promise<AcquireTokenResult>;
  
  // Login user interactively
  login(options: LoginOptions): Promise<LoginResult>;
  
  // Logout user (returns boolean)
  logout(options?: LogoutOptions): Promise<boolean>;
  
  // Handle authentication redirect (returns AuthenticationResult | null)
  handleRedirect(): Promise<AuthenticationResult | null>;
}

// Note: defaultAccount and other deprecated v2 properties are available only
//       when using a v2-compatible proxy via createProxyProvider()

Module Hoisting

The module implements a hoisting pattern where the authentication provider is created once at the root level and shared across all sub-modules. This ensures consistent authentication state throughout your application while maintaining security and performance.

[!IMPORTANT] Configure the auth module only in the root Fusion Framework instance - Sub-instances will automatically inherit the authentication configuration from the parent.

Migration Guide

MSAL v2 to v4 Migration

This package has been upgraded from MSAL Browser v2 to v4, providing the latest security improvements and features from Microsoft.

What Changed in v4

New MSAL Browser v4 Features:

  • Enhanced security with improved token management
  • Better performance and memory usage
  • New authentication API structure with nested request objects
  • Improved error handling and retry mechanisms

Architecture Changes:

  • Module Hoisting: The module uses module hoisting, meaning sub-module instances proxy the parent module instance
  • Shared Authentication State: Authentication state is shared across all module instances
  • Async Initialization: New initialize() method must be called before using the provider

Breaking Changes

  • Auto-initialization via Framework

    // The provider initializes automatically when framework loads
    const framework = await initialize(configurator);
    const auth = framework.auth; // Already initialized
    
    // Manual initialization is only needed for standalone usage
    const provider = new MsalProvider(config);
    await provider.initialize();
    
  • API Method Signature Updates

    • logout() now returns Promise<boolean> instead of Promise<void>
    • handleRedirect() now returns Promise<AuthenticationResult | null> instead of Promise<void>
    • Methods now expect nested request objects (v4 format)
  • Account Property Changes

    • Use account property (returns AccountInfo | null) - v4 native
    • defaultAccount is deprecated and only available via v2 proxy layer
    • Migration: Replace defaultAccount with account throughout your code

Migration Steps

  • Update Token Acquisition (Recommended)

    // Before (v2 format - still works via proxy)
    const token = await framework.auth.acquireAccessToken({ 
      scopes: ['api.read'] 
    });
    
    // After (v4 format - recommended)
    const token = await framework.auth.acquireAccessToken({ 
      request: { scopes: ['api.read'] } 
    });
    
  • Update Logout Handling

    // Before
    await framework.auth.logout();
    
    // After (check return value)
    const success = await framework.auth.logout();
    if (success) {
      // Handle successful logout
    }
    
  • Update Redirect Handling

    // Before
    await framework.auth.handleRedirect();
    
    // After (handle result)
    const result = await framework.auth.handleRedirect();
    if (result?.account) {
      // User authenticated successfully
      console.log('Logged in as:', result.account.username);
    }
    
  • Update Configuration (if needed)

    // Ensure only the root module configures MSAL
    enableMSAL(configurator, (builder) => {
      builder.setClientConfig({
        auth: {
          clientId: 'your-client-id',
          tenantId: 'your-tenant-id',
          redirectUri: 'https://your-app.com/callback'
        }
      });
      builder.setRequiresAuth(true);
    });
    
  • Remove Duplicate Configurations: Remove MSAL configuration from child modules

Backward Compatibility

The module includes a v2 proxy layer that automatically converts v2 API calls to v4 format. This means:

  • ✅ Existing code continues to work without changes
  • ✅ Legacy format { scopes: [] } is still supported
  • ✅ Deprecated v2 properties like defaultAccount are available via v2 proxy (with deprecation warnings)
  • ⚠️ New v4 features require using v4 format

Benefits of Migration

  • Better Security: Latest MSAL v4 security improvements and token handling
  • Improved Performance: Faster token acquisition, better caching, reduced memory usage
  • Enhanced Error Handling: More robust error recovery and retry mechanisms
  • Future-Proof: Access to latest Microsoft authentication features and updates
  • Shared State: Improved authentication state management across app scopes via module hoisting
  • Better Developer Experience: Cleaner API, better TypeScript support, comprehensive documentation

Troubleshooting

Common Issues

IssueSolution
Authentication LoopEnsure redirect URIs match your application's routing
Token Acquisition FailsCheck that required scopes are properly configured
Module Not FoundEnsure the module is properly configured and framework is initialized
Multiple MSAL InstancesRemove duplicate configurations from child modules
Redirect Returns VoidFor redirect flows, use handleRedirect() after navigation completes
Token Empty/UndefinedVerify user is authenticated and scopes are correct

Getting Help

  • 📖 MSAL Cookbook - Complete working examples
  • 🐛 Report Issues - Bug reports and feature requests

Version Management

The MSAL module includes built-in version checking to ensure compatibility between different MSAL library versions.

Version Resolution

import { resolveVersion, VersionError } from '@equinor/fusion-framework-module-msal/versioning';

// Resolve and validate a version
const result = resolveVersion('2.0.0');
console.log(result.isLatest); // false
console.log(result.satisfiesLatest); // true
console.log(result.enumVersion); // MsalModuleVersion.V2

Version Checking Behavior

  • Major Version Incompatibility: Throws VersionError if requested major version is greater than latest
  • Minor Version Mismatch: Logs warning but allows execution
  • Patch Differences: Ignored for compatibility
  • Invalid Versions: Throws VersionError with descriptive message

API Reference

resolveVersion(version: string | SemVer): ResolvedVersion

Resolves and validates a version string against the latest available MSAL version.

Parameters:

  • version - Version string or SemVer object to resolve

Returns: ResolvedVersion object containing:

  • wantedVersion: SemVer - The parsed requested version
  • latestVersion: SemVer - The latest available version
  • isLatest: boolean - Whether the version is exactly the latest
  • satisfiesLatest: boolean - Whether the major version matches latest
  • enumVersion: MsalModuleVersion - Corresponding enum version

Throws: VersionError for invalid or incompatible versions

VersionError

Error class for version-related issues with the following types:

  • InvalidVersion - Requested version is not a valid semver
  • InvalidLatestVersion - Latest version parsing failed (build issue)
  • MajorIncompatibility - Major version is greater than latest
  • MinorMismatch - Minor version differs (warning only)
  • PatchDifference - Patch version differs (info only)
  • IncompatibleVersion - General incompatibility

Error Handling

import { resolveVersion, VersionError } from '@equinor/fusion-framework-module-msal/versioning';

try {
  const result = resolveVersion('3.0.0'); // Assuming latest is 2.x
} catch (error) {
  if (error instanceof VersionError) {
    console.error('Version error:', error.message);
    console.error('Requested:', error.requestedVersion);
    console.error('Latest:', error.latestVersion);
    console.error('Type:', error.type);
  }
}

Additional Resources

Official Documentation

Learning Resources

Support

FAQs

Package last updated on 31 Oct 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts