@equinor/fusion-framework-vite-plugin-spa 3.1.5 → 3.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @equinor/fusion-framework-vite-plugin-spa
2
2
 
3
+ ## 3.1.7
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [[`dcf51aa`](https://github.com/equinor/fusion-framework/commit/dcf51aa87ac79200893ec4909632554464e75055)]:
8
+ - @equinor/fusion-framework-module-msal@7.2.0
9
+
10
+ ## 3.1.6
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies [[`0b34d5d`](https://github.com/equinor/fusion-framework/commit/0b34d5d895c740a77fc995abeca910fdca1cf633)]:
15
+ - @equinor/fusion-framework-module-msal@7.1.0
16
+
3
17
  ## 3.1.5
4
18
 
5
19
  ### Patch Changes
@@ -1,3 +1,3 @@
1
1
  // Generated by genversion.
2
- export const version = '3.1.5';
2
+ export const version = '3.1.7';
3
3
  //# sourceMappingURL=version.js.map
@@ -153,8 +153,8 @@ function requireRe () {
153
153
 
154
154
  // ## Pre-release Version Identifier
155
155
  // A numeric identifier, or a non-numeric identifier.
156
- // Non-numberic identifiers include numberic identifiers but can be longer.
157
- // Therefore non-numberic identifiers must go first.
156
+ // Non-numeric identifiers include numeric identifiers but can be longer.
157
+ // Therefore non-numeric identifiers must go first.
158
158
 
159
159
  createToken('PRERELEASEIDENTIFIER', `(?:${src[t.NONNUMERICIDENTIFIER]
160
160
  }|${src[t.NUMERICIDENTIFIER]})`);
@@ -850,7 +850,7 @@ function requireDiff () {
850
850
  return prefix + 'patch'
851
851
  }
852
852
 
853
- // high and low are preleases
853
+ // high and low are prereleases
854
854
  return 'prerelease'
855
855
  };
856
856
 
@@ -2409,7 +2409,7 @@ function requireSubset () {
2409
2409
  // - If LT
2410
2410
  // - If LT.semver is greater than any < or <= comp in C, return false
2411
2411
  // - If LT is <=, and LT.semver does not satisfy every C, return false
2412
- // - If GT.semver has a prerelease, and not in prerelease mode
2412
+ // - If LT.semver has a prerelease, and not in prerelease mode
2413
2413
  // - If no C has a prerelease and the LT.semver tuple, return false
2414
2414
  // - Else return true
2415
2415
 
@@ -40463,7 +40463,7 @@ const createClientLogCallback = (provider, metadata, scope) => {
40463
40463
  };
40464
40464
 
40465
40465
  // Generated by genversion.
40466
- const version$2 = '7.0.0';
40466
+ const version$2 = '7.2.0';
40467
40467
 
40468
40468
  /**
40469
40469
  * Zod schema for telemetry configuration validation.
@@ -40488,6 +40488,8 @@ const MsalConfigSchema = z.object({
40488
40488
  provider: z.custom().optional(),
40489
40489
  requiresAuth: z.boolean().optional(),
40490
40490
  redirectUri: z.string().optional(),
40491
+ loginHint: z.string().optional(),
40492
+ authCode: z.string().optional(),
40491
40493
  version: z.string().transform((x) => String(semver.coerce(x))),
40492
40494
  telemetry: TelemetryConfigSchema,
40493
40495
  });
@@ -40555,6 +40557,37 @@ class MsalConfigurator extends BaseConfigBuilder {
40555
40557
  this.#msalConfig = config;
40556
40558
  return this;
40557
40559
  }
40560
+ /**
40561
+ * Sets a backend-issued authorization code for token exchange.
40562
+ *
40563
+ * This enables the MSAL module to exchange a backend-generated auth code for tokens
40564
+ * during initialization, allowing users to be automatically signed in without triggering
40565
+ * an interactive MSAL login flow. The auth code is exchanged before the requiresAuth check,
40566
+ * so tokens are cached and no login prompt appears.
40567
+ *
40568
+ * This follows Microsoft's standard SPA Auth Code Flow pattern and is compatible with
40569
+ * MSAL Browser's acquireTokenByCode() method.
40570
+ *
40571
+ * @param authCode - The authorization code issued by the backend
40572
+ * @returns The configurator instance for method chaining
40573
+ *
40574
+ * @example
40575
+ * ```typescript
40576
+ * // Backend provides auth code in HTML/config
40577
+ * const config = { auth: { code: getAuthCodeFromBackend() } };
40578
+ * configurator.setAuthCode(config.auth.code);
40579
+ * ```
40580
+ *
40581
+ * @remarks
40582
+ * - Auth codes are single-use and short-lived (typically 5-10 minutes)
40583
+ * - The exchange happens during module initialization before requiresAuth check
40584
+ * - If exchange fails, the provider falls back to standard MSAL authentication flows
40585
+ * - Requires backend to be configured with SPA Auth Code support
40586
+ */
40587
+ setAuthCode(authCode) {
40588
+ this._set('authCode', async () => authCode);
40589
+ return this;
40590
+ }
40558
40591
  /**
40559
40592
  * Sets whether authentication is required for the application.
40560
40593
  *
@@ -40578,6 +40611,24 @@ class MsalConfigurator extends BaseConfigBuilder {
40578
40611
  this._set('requiresAuth', async () => requiresAuth);
40579
40612
  return this;
40580
40613
  }
40614
+ /**
40615
+ * Sets a default login hint for authentication flows.
40616
+ *
40617
+ * The login hint is used to pre-fill the username during authentication and
40618
+ * enables silent SSO when no account is available.
40619
+ *
40620
+ * @param loginHint - The preferred username/email to use as login hint
40621
+ * @returns The configurator instance for method chaining
40622
+ *
40623
+ * @example
40624
+ * ```typescript
40625
+ * configurator.setLoginHint('user@company.com');
40626
+ * ```
40627
+ */
40628
+ setLoginHint(loginHint) {
40629
+ this._set('loginHint', async () => loginHint);
40630
+ return this;
40631
+ }
40581
40632
  /**
40582
40633
  * @deprecated - since version 5.1.0, use setClient instead
40583
40634
  */
@@ -41441,6 +41492,8 @@ class MsalProvider extends BaseModuleProvider {
41441
41492
  #client;
41442
41493
  #telemetry;
41443
41494
  #requiresAuth;
41495
+ #authCode;
41496
+ #loginHint;
41444
41497
  /**
41445
41498
  * The MSAL module version enum value indicating the API compatibility level.
41446
41499
  *
@@ -41498,6 +41551,10 @@ class MsalProvider extends BaseModuleProvider {
41498
41551
  });
41499
41552
  this.#requiresAuth = config.requiresAuth;
41500
41553
  this.#telemetry = config.telemetry;
41554
+ this.#loginHint = config.loginHint;
41555
+ // Extract auth code from config if present
41556
+ // This will be used during initialize to exchange for tokens
41557
+ this.#authCode = config.authCode;
41501
41558
  // Validate required client configuration
41502
41559
  if (!config.client) {
41503
41560
  const error = new Error('Client is required, please provide a valid client in the configuration');
@@ -41513,12 +41570,17 @@ class MsalProvider extends BaseModuleProvider {
41513
41570
  *
41514
41571
  * This method must be called before using any authentication operations. It performs:
41515
41572
  * - Client initialization
41573
+ * - Auth code exchange (if backend-issued code provided)
41516
41574
  * - Redirect result handling (if returning from auth flow)
41517
41575
  * - Automatic login attempt if requiresAuth is enabled and no valid session exists
41518
41576
  *
41519
41577
  * @returns Promise that resolves when initialization is complete
41520
41578
  *
41521
41579
  * @remarks
41580
+ * Auth code exchange happens before the requiresAuth check, allowing automatic sign-in
41581
+ * without user interaction when a valid backend-issued code is provided. If exchange fails,
41582
+ * the provider falls back to standard MSAL authentication flows.
41583
+ *
41522
41584
  * The provider will attempt automatic login with empty scopes if requiresAuth is true.
41523
41585
  * Apps should call acquireToken with actual scopes after initialization completes.
41524
41586
  */
@@ -41526,6 +41588,52 @@ class MsalProvider extends BaseModuleProvider {
41526
41588
  const measurement = this._trackMeasurement('initialize', TelemetryLevel.Debug);
41527
41589
  // Initialize the underlying MSAL client first
41528
41590
  await this.#client.initialize();
41591
+ // Priority 0: Exchange auth code if provided by backend
41592
+ // This must happen before the requiresAuth check so tokens are cached
41593
+ if (this.#authCode) {
41594
+ try {
41595
+ this._trackEvent('initialize.exchanging-auth-code', TelemetryLevel.Information);
41596
+ // Use MSAL's acquireTokenByCode to exchange backend auth code for tokens
41597
+ // This follows Microsoft's standard SPA Auth Code Flow pattern
41598
+ const clientId = this.#client.clientId;
41599
+ if (!clientId) {
41600
+ throw new Error('Client ID is required for auth code exchange');
41601
+ }
41602
+ // Exchange the auth code for tokens using the client ID's default scope.
41603
+ // The `/.default` scope represents all permissions configured for this app in Entra ID,
41604
+ // ensuring the exchanged tokens have the correct app-level permissions without requiring
41605
+ // the caller to specify scopes. This follows MSAL's recommended SPA auth code pattern.
41606
+ // This method is inherited from PublicClientApplication (MSAL Browser v4+)
41607
+ const result = await this.#client.acquireTokenByCode({
41608
+ code: this.#authCode,
41609
+ scopes: [`${clientId}/.default`],
41610
+ });
41611
+ // Successfully exchanged auth code - set active account
41612
+ if (result.account) {
41613
+ this.#client.setActiveAccount(result.account);
41614
+ this._trackEvent('initialize.auth-code-exchanged-account', TelemetryLevel.Information, {
41615
+ properties: {
41616
+ username: result.account.username,
41617
+ },
41618
+ });
41619
+ }
41620
+ }
41621
+ catch (error) {
41622
+ // Auth code exchange failed - log and fall back to standard flows
41623
+ this._trackException('initialize.auth-code-exchange-failed', TelemetryLevel.Warning, {
41624
+ exception: error instanceof Error ? error : new Error(String(error)),
41625
+ properties: {
41626
+ message: error instanceof Error ? error.message : String(error),
41627
+ reason: 'Auth code exchange failed, falling back to standard authentication flows',
41628
+ },
41629
+ });
41630
+ // Continue to requiresAuth check - will trigger standard login if needed
41631
+ }
41632
+ finally {
41633
+ // Clear auth code to avoid repeated attempts
41634
+ this.#authCode = undefined;
41635
+ }
41636
+ }
41529
41637
  // Only attempt authentication if this provider requires it
41530
41638
  if (this.#requiresAuth) {
41531
41639
  // Priority 1: Check if returning from redirect-based authentication
@@ -41704,6 +41812,8 @@ class MsalProvider extends BaseModuleProvider {
41704
41812
  */
41705
41813
  async login(options) {
41706
41814
  const { behavior = 'redirect', silent = true, request } = options;
41815
+ request.loginHint ??=
41816
+ this.#loginHint ?? this.account?.username ?? this.account?.loginHint ?? undefined;
41707
41817
  // Determine if silent login is possible based on available account/hint information
41708
41818
  // Silent login requires either an account object or a loginHint to work
41709
41819
  const canLoginSilently = silent && (request.account || request.loginHint);
@@ -44818,7 +44928,7 @@ async function registerServiceWorker(framework) {
44818
44928
  }
44819
44929
 
44820
44930
  // Generated by genversion.
44821
- const version = '3.1.5';
44931
+ const version = '3.1.7';
44822
44932
 
44823
44933
  // Allow dynamic import without vite
44824
44934
  const importWithoutVite = (path) => import(/* @vite-ignore */ path);