@equinor/fusion-framework-module-msal 7.3.1 → 8.0.0
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 +32 -20
- package/dist/esm/MsalConfigurator.js +11 -2
- package/dist/esm/MsalConfigurator.js.map +1 -1
- package/dist/esm/MsalProvider.js +33 -3
- package/dist/esm/MsalProvider.js.map +1 -1
- package/dist/esm/index.js +26 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/util/compare-origin.js +8 -1
- package/dist/esm/util/compare-origin.js.map +1 -1
- package/dist/esm/util/normalize-uri.js +14 -4
- package/dist/esm/util/normalize-uri.js.map +1 -1
- package/dist/esm/util/redirect.js +10 -5
- package/dist/esm/util/redirect.js.map +1 -1
- package/dist/esm/v2/create-proxy-client.js +10 -8
- package/dist/esm/v2/create-proxy-client.js.map +1 -1
- package/dist/esm/v2/map-account-info.js +6 -3
- package/dist/esm/v2/map-account-info.js.map +1 -1
- package/dist/esm/v2/map-authentication-result.js +7 -3
- package/dist/esm/v2/map-authentication-result.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/MsalConfigurator.d.ts +11 -2
- package/dist/types/index.d.ts +26 -0
- package/dist/types/v2/IAuthClient.interface.d.ts +23 -0
- package/dist/types/v2/MsalProvider.interface.d.ts +11 -1
- package/dist/types/v2/create-proxy-client.d.ts +10 -8
- package/dist/types/v2/map-account-info.d.ts +6 -3
- package/dist/types/v2/map-authentication-result.d.ts +7 -3
- package/dist/types/version.d.ts +1 -1
- package/package.json +13 -13
- package/src/MsalConfigurator.ts +11 -2
- package/src/MsalProvider.ts +36 -3
- package/src/index.ts +27 -0
- package/src/util/compare-origin.ts +8 -1
- package/src/util/normalize-uri.ts +14 -4
- package/src/util/redirect.ts +10 -5
- package/src/v2/IAuthClient.interface.ts +23 -0
- package/src/v2/MsalProvider.interface.ts +11 -1
- package/src/v2/create-proxy-client.ts +10 -8
- package/src/v2/map-account-info.ts +6 -3
- package/src/v2/map-authentication-result.ts +7 -3
- package/src/version.ts +1 -1
|
@@ -133,7 +133,12 @@ export declare class MsalConfigurator extends BaseConfigBuilder<MsalConfig> {
|
|
|
133
133
|
*/
|
|
134
134
|
setLoginHint(loginHint?: string): this;
|
|
135
135
|
/**
|
|
136
|
-
*
|
|
136
|
+
* Sets a pre-configured MSAL provider instance directly.
|
|
137
|
+
*
|
|
138
|
+
* @deprecated Since version 5.1.0. Use {@link MsalConfigurator.setClient | setClient} instead.
|
|
139
|
+
*
|
|
140
|
+
* @param provider - Pre-configured provider instance, or undefined to clear
|
|
141
|
+
* @returns The configurator instance for method chaining
|
|
137
142
|
*/
|
|
138
143
|
setProvider(provider?: IMsalProvider): this;
|
|
139
144
|
/**
|
|
@@ -166,7 +171,11 @@ export declare class MsalConfigurator extends BaseConfigBuilder<MsalConfig> {
|
|
|
166
171
|
setTelemetry(telemetry: ITelemetryProvider | undefined): this;
|
|
167
172
|
/**
|
|
168
173
|
* Sets optional metadata to be included on all MSAL telemetry events.
|
|
169
|
-
*
|
|
174
|
+
*
|
|
175
|
+
* @deprecated Use {@link MsalConfigurator.setTelemetry | setTelemetry} instead.
|
|
176
|
+
*
|
|
177
|
+
* @param metadata - Key-value metadata to attach to telemetry events, or undefined to clear
|
|
178
|
+
* @returns The configurator instance for method chaining
|
|
170
179
|
*/
|
|
171
180
|
setTelemetryMetadata(metadata: Record<string, unknown> | undefined): this;
|
|
172
181
|
/**
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
*
|
|
4
|
+
* MSAL authentication module for Fusion Framework.
|
|
5
|
+
*
|
|
6
|
+
* Provides Microsoft Authentication Library (MSAL) integration with support for:
|
|
7
|
+
* - Azure AD / Entra ID authentication (SSO, popup, redirect)
|
|
8
|
+
* - Automatic token management with silent refresh
|
|
9
|
+
* - Module hoisting for shared auth state across application scopes
|
|
10
|
+
* - Backward-compatible v2 proxy layer alongside native MSAL v4/v5 API
|
|
11
|
+
* - Backend-issued SPA authorization code exchange
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { enableMSAL } from '@equinor/fusion-framework-module-msal';
|
|
16
|
+
*
|
|
17
|
+
* enableMSAL(configurator, (builder) => {
|
|
18
|
+
* builder.setClientConfig({
|
|
19
|
+
* auth: { clientId: 'your-client-id', tenantId: 'your-tenant-id' },
|
|
20
|
+
* });
|
|
21
|
+
* builder.setRequiresAuth(true);
|
|
22
|
+
* });
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @module @equinor/fusion-framework-module-msal
|
|
26
|
+
*/
|
|
1
27
|
export { module, configureMsal, enableMSAL, type MsalModule, type AuthConfigFn, } from './module';
|
|
2
28
|
export type { IMsalProvider } from './MsalProvider.interface';
|
|
3
29
|
export type { IMsalClient } from './MsalClient.interface';
|
|
@@ -1,12 +1,35 @@
|
|
|
1
1
|
import type { AccountInfo as AccountInfoBase, AuthenticationResult, IPublicClientApplication } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Simplified ID token claims used by the v2 compatibility layer.
|
|
4
|
+
*
|
|
5
|
+
* @property aud - Token audience (application ID)
|
|
6
|
+
* @property exp - Token expiration time (seconds since epoch)
|
|
7
|
+
*/
|
|
2
8
|
export type IdTokenClaims = {
|
|
3
9
|
aud: string;
|
|
4
10
|
exp: number;
|
|
5
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
* Extended account information for v2 compatibility.
|
|
14
|
+
*
|
|
15
|
+
* Augments the base v2 `AccountInfo` with typed ID token claims.
|
|
16
|
+
*/
|
|
6
17
|
export type AccountInfo = AccountInfoBase & {
|
|
7
18
|
idTokenClaims?: IdTokenClaims;
|
|
8
19
|
};
|
|
20
|
+
/**
|
|
21
|
+
* Authentication behavior type for v2-compatible login and token flows.
|
|
22
|
+
*
|
|
23
|
+
* - `'popup'` — Opens a popup window for authentication
|
|
24
|
+
* - `'redirect'` — Navigates the browser to the Microsoft login page
|
|
25
|
+
*/
|
|
9
26
|
export type AuthBehavior = 'popup' | 'redirect';
|
|
27
|
+
/**
|
|
28
|
+
* Simplified authentication request for v2-compatible methods.
|
|
29
|
+
*
|
|
30
|
+
* @property scopes - Optional OAuth scopes to request (e.g. `['User.Read']`)
|
|
31
|
+
* @property loginHint - Optional username hint to pre-fill the login form
|
|
32
|
+
*/
|
|
10
33
|
export type AuthRequest = {
|
|
11
34
|
scopes?: string[];
|
|
12
35
|
loginHint?: string;
|
|
@@ -7,7 +7,17 @@ import type { IAuthClient } from './IAuthClient.interface';
|
|
|
7
7
|
*
|
|
8
8
|
* This interface defines the contract for authentication providers that maintain
|
|
9
9
|
* backward compatibility with MSAL v2 API while using MSAL v4 implementation
|
|
10
|
-
* under the hood.
|
|
10
|
+
* under the hood. Used by the v2 proxy layer during gradual migration scenarios.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* // Obtain a v2 proxy from the current provider
|
|
15
|
+
* const v2Provider: IMsalProvider = provider.createProxyProvider('2.0.0');
|
|
16
|
+
*
|
|
17
|
+
* // Use v2-style API
|
|
18
|
+
* await v2Provider.login();
|
|
19
|
+
* const token = await v2Provider.acquireAccessToken({ scopes: ['User.Read'] });
|
|
20
|
+
* ```
|
|
11
21
|
*/
|
|
12
22
|
export interface IMsalProvider {
|
|
13
23
|
/** Current version of the provider (MSAL module version) */
|
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
import type { IMsalClient } from '../MsalClient.interface';
|
|
2
2
|
import type { IAuthClient } from './IAuthClient.interface';
|
|
3
3
|
/**
|
|
4
|
-
* Creates a v2-compatible proxy
|
|
4
|
+
* Creates a v2-compatible proxy wrapper around an MSAL v4 client.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* and
|
|
6
|
+
* The proxy intercepts property access on the v4 `IMsalClient` and adapts method
|
|
7
|
+
* signatures, return types, and account data to match the v2 `IAuthClient` interface.
|
|
8
|
+
* This allows consumer code written against MSAL v2 to continue working unchanged
|
|
9
|
+
* while the underlying implementation uses MSAL v4/v5.
|
|
8
10
|
*
|
|
9
|
-
* @param client - The MSAL v4
|
|
10
|
-
* @returns A proxy
|
|
11
|
+
* @param client - The MSAL v4 `IMsalClient` instance to wrap
|
|
12
|
+
* @returns A proxy implementing the v2-compatible `IAuthClient` interface
|
|
11
13
|
*
|
|
12
14
|
* @example
|
|
13
15
|
* ```typescript
|
|
14
|
-
* const v4Client = new
|
|
15
|
-
* const v2Client =
|
|
16
|
+
* const v4Client = new MsalClient(config);
|
|
17
|
+
* const v2Client = createProxyClient(v4Client);
|
|
16
18
|
*
|
|
17
19
|
* // Use v2-compatible methods
|
|
18
20
|
* const accounts = v2Client.getAllAccounts();
|
|
19
|
-
* const
|
|
21
|
+
* const result = await v2Client.acquireTokenSilent({ scopes: ['User.Read'], account });
|
|
20
22
|
* ```
|
|
21
23
|
*/
|
|
22
24
|
export declare function createProxyClient(client: IMsalClient): IAuthClient;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import type { AccountInfo } from '@azure/msal-browser';
|
|
2
2
|
import type { AccountInfo as AccountInfo_v2 } from './types';
|
|
3
3
|
/**
|
|
4
|
-
* Maps current AccountInfo to v2 AccountInfo format.
|
|
4
|
+
* Maps a current (v4/v5) `AccountInfo` object to the v2-compatible `AccountInfo` format.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Strips properties that don't exist in v2, ensuring backward-compatible serialization
|
|
7
|
+
* and type safety when passing account data through the v2 proxy layer.
|
|
8
|
+
*
|
|
9
|
+
* @param account - The current MSAL v4/v5 `AccountInfo` to convert
|
|
10
|
+
* @returns A v2-compatible `AccountInfo` containing only fields recognised by MSAL v2 consumers
|
|
8
11
|
*/
|
|
9
12
|
export declare function mapAccountInfo(account: AccountInfo): AccountInfo_v2;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import type { AuthenticationResult } from '@azure/msal-browser';
|
|
2
2
|
import type { AuthenticationResult as AuthenticationResult_v2 } from './types';
|
|
3
3
|
/**
|
|
4
|
-
* Maps current AuthenticationResult to v2
|
|
4
|
+
* Maps a current (v4/v5) `AuthenticationResult` to the v2-compatible format.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Converts the full authentication result — including the nested account object —
|
|
7
|
+
* to the subset of fields that MSAL v2 consumers expect. This enables the v2 proxy
|
|
8
|
+
* layer to return type-safe results without exposing v4/v5-only properties.
|
|
9
|
+
*
|
|
10
|
+
* @param result - The current MSAL v4/v5 `AuthenticationResult` to convert
|
|
11
|
+
* @returns A v2-compatible `AuthenticationResult` with mapped account and token fields
|
|
8
12
|
*/
|
|
9
13
|
export declare function mapAuthenticationResult(result: AuthenticationResult): AuthenticationResult_v2;
|
package/dist/types/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "
|
|
1
|
+
export declare const version = "8.0.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@equinor/fusion-framework-module-msal",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"description": "Microsoft Authentication Library (MSAL) integration module for Fusion Framework",
|
|
5
5
|
"main": "dist/esm/index.js",
|
|
6
6
|
"types": "dist/types/index.d.ts",
|
|
@@ -46,20 +46,20 @@
|
|
|
46
46
|
"@azure/msal-browser": "^5.0.2"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@types/semver": "^7.
|
|
50
|
-
"semver": "^7.
|
|
51
|
-
"typescript": "^5.
|
|
52
|
-
"zod": "^4.
|
|
53
|
-
"@equinor/fusion-framework-module": "^
|
|
54
|
-
"@equinor/fusion-framework-module-telemetry": "^
|
|
49
|
+
"@types/semver": "^7.7.1",
|
|
50
|
+
"semver": "^7.7.4",
|
|
51
|
+
"typescript": "^5.9.3",
|
|
52
|
+
"zod": "^4.3.6",
|
|
53
|
+
"@equinor/fusion-framework-module": "^6.0.0",
|
|
54
|
+
"@equinor/fusion-framework-module-telemetry": "^5.0.0"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
|
-
"@types/semver": "^7.
|
|
58
|
-
"semver": "^7.
|
|
59
|
-
"typescript": "^5.
|
|
60
|
-
"zod": "^4.
|
|
61
|
-
"@equinor/fusion-framework-module": "^
|
|
62
|
-
"@equinor/fusion-framework-module-telemetry": "^
|
|
57
|
+
"@types/semver": "^7.0.0",
|
|
58
|
+
"semver": "^7.0.0",
|
|
59
|
+
"typescript": "^5.0.0",
|
|
60
|
+
"zod": "^4.0.0",
|
|
61
|
+
"@equinor/fusion-framework-module": "^6.0.0",
|
|
62
|
+
"@equinor/fusion-framework-module-telemetry": "^5.0.0"
|
|
63
63
|
},
|
|
64
64
|
"peerDependenciesMeta": {
|
|
65
65
|
"@equinor/fusion-framework-module-telemetry": {
|
package/src/MsalConfigurator.ts
CHANGED
|
@@ -206,7 +206,12 @@ export class MsalConfigurator extends BaseConfigBuilder<MsalConfig> {
|
|
|
206
206
|
}
|
|
207
207
|
|
|
208
208
|
/**
|
|
209
|
-
*
|
|
209
|
+
* Sets a pre-configured MSAL provider instance directly.
|
|
210
|
+
*
|
|
211
|
+
* @deprecated Since version 5.1.0. Use {@link MsalConfigurator.setClient | setClient} instead.
|
|
212
|
+
*
|
|
213
|
+
* @param provider - Pre-configured provider instance, or undefined to clear
|
|
214
|
+
* @returns The configurator instance for method chaining
|
|
210
215
|
*/
|
|
211
216
|
setProvider(provider?: IMsalProvider): this {
|
|
212
217
|
this._set('provider', async () => provider);
|
|
@@ -251,7 +256,11 @@ export class MsalConfigurator extends BaseConfigBuilder<MsalConfig> {
|
|
|
251
256
|
|
|
252
257
|
/**
|
|
253
258
|
* Sets optional metadata to be included on all MSAL telemetry events.
|
|
254
|
-
*
|
|
259
|
+
*
|
|
260
|
+
* @deprecated Use {@link MsalConfigurator.setTelemetry | setTelemetry} instead.
|
|
261
|
+
*
|
|
262
|
+
* @param metadata - Key-value metadata to attach to telemetry events, or undefined to clear
|
|
263
|
+
* @returns The configurator instance for method chaining
|
|
255
264
|
*/
|
|
256
265
|
setTelemetryMetadata(metadata: Record<string, unknown> | undefined): this {
|
|
257
266
|
this._set('telemetry.metadata', async () => metadata);
|
package/src/MsalProvider.ts
CHANGED
|
@@ -177,6 +177,20 @@ export class MsalProvider extends BaseModuleProvider<MsalConfig> implements IMsa
|
|
|
177
177
|
* Apps should call acquireToken with actual scopes after initialization completes.
|
|
178
178
|
*/
|
|
179
179
|
async initialize(): Promise<void> {
|
|
180
|
+
// Guard: skip authentication when running inside MSAL's hidden iframe.
|
|
181
|
+
// MSAL uses a hidden iframe for silent token renewal (acquireTokenSilent).
|
|
182
|
+
// The iframe loads the app URL, which would re-initialize MSAL and attempt
|
|
183
|
+
// loginRedirect(), causing the "block_iframe_reload" error. Detect this
|
|
184
|
+
// by checking if we're in an iframe and the URL contains MSAL's hash params.
|
|
185
|
+
if (typeof window !== 'undefined' && window !== window.parent) {
|
|
186
|
+
// Running inside an iframe — let the parent handle authentication.
|
|
187
|
+
// Still initialize the client so handleRedirectPromise can process
|
|
188
|
+
// the auth response and post it back to the parent frame.
|
|
189
|
+
await this.#client.initialize();
|
|
190
|
+
await this.#client.handleRedirectPromise();
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
180
194
|
const measurement = this._trackMeasurement('initialize', TelemetryLevel.Debug);
|
|
181
195
|
// Initialize the underlying MSAL client first
|
|
182
196
|
await this.#client.initialize();
|
|
@@ -320,11 +334,16 @@ export class MsalProvider extends BaseModuleProvider<MsalConfig> implements IMsa
|
|
|
320
334
|
async acquireToken(
|
|
321
335
|
options?: AcquireTokenOptions | AcquireTokenOptionsLegacy,
|
|
322
336
|
): Promise<AcquireTokenResult> {
|
|
337
|
+
// Guard: when running inside MSAL's hidden iframe, only attempt silent
|
|
338
|
+
// acquisition. Interactive flows (redirect/popup) must never be triggered
|
|
339
|
+
// from an iframe — MSAL will throw "block_iframe_reload".
|
|
340
|
+
const inIframe = typeof window !== 'undefined' && window !== window.parent;
|
|
341
|
+
|
|
323
342
|
// Determine behavior and silent options, with defaults (redirect and true respectively)
|
|
324
|
-
const behavior = options?.behavior ?? 'redirect';
|
|
343
|
+
const behavior = inIframe ? 'redirect' : (options?.behavior ?? 'redirect');
|
|
325
344
|
|
|
326
|
-
//
|
|
327
|
-
const silent = options?.silent ?? true;
|
|
345
|
+
// When in an iframe, force silent-only to prevent interactive fallback
|
|
346
|
+
const silent = inIframe ? true : (options?.silent ?? true);
|
|
328
347
|
|
|
329
348
|
const defaultScopes = this.defaultScopes;
|
|
330
349
|
|
|
@@ -383,6 +402,15 @@ export class MsalProvider extends BaseModuleProvider<MsalConfig> implements IMsa
|
|
|
383
402
|
measurement?.measure();
|
|
384
403
|
return result;
|
|
385
404
|
} catch (error) {
|
|
405
|
+
// Inside MSAL's hidden iframe, silent acquisition may fail and the client
|
|
406
|
+
// would fall back to acquireTokenRedirect which throws "block_iframe_reload".
|
|
407
|
+
// Suppress this — the parent frame handles interactive auth.
|
|
408
|
+
if (inIframe) {
|
|
409
|
+
this._trackEvent('acquireToken.suppressed-in-iframe', TelemetryLevel.Debug, {
|
|
410
|
+
properties: telemetryProperties,
|
|
411
|
+
});
|
|
412
|
+
return undefined;
|
|
413
|
+
}
|
|
386
414
|
this._trackException('acquireToken-failed', TelemetryLevel.Error, {
|
|
387
415
|
exception: error as Error,
|
|
388
416
|
properties: telemetryProperties,
|
|
@@ -439,6 +467,11 @@ export class MsalProvider extends BaseModuleProvider<MsalConfig> implements IMsa
|
|
|
439
467
|
* ```
|
|
440
468
|
*/
|
|
441
469
|
async login(options: LoginOptions): Promise<LoginResult> {
|
|
470
|
+
// Guard: never attempt interactive login inside MSAL's hidden iframe.
|
|
471
|
+
if (typeof window !== 'undefined' && window !== window.parent) {
|
|
472
|
+
return undefined;
|
|
473
|
+
}
|
|
474
|
+
|
|
442
475
|
const { behavior = 'redirect', silent = true, request } = options;
|
|
443
476
|
|
|
444
477
|
request.loginHint ??=
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
*
|
|
4
|
+
* MSAL authentication module for Fusion Framework.
|
|
5
|
+
*
|
|
6
|
+
* Provides Microsoft Authentication Library (MSAL) integration with support for:
|
|
7
|
+
* - Azure AD / Entra ID authentication (SSO, popup, redirect)
|
|
8
|
+
* - Automatic token management with silent refresh
|
|
9
|
+
* - Module hoisting for shared auth state across application scopes
|
|
10
|
+
* - Backward-compatible v2 proxy layer alongside native MSAL v4/v5 API
|
|
11
|
+
* - Backend-issued SPA authorization code exchange
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { enableMSAL } from '@equinor/fusion-framework-module-msal';
|
|
16
|
+
*
|
|
17
|
+
* enableMSAL(configurator, (builder) => {
|
|
18
|
+
* builder.setClientConfig({
|
|
19
|
+
* auth: { clientId: 'your-client-id', tenantId: 'your-tenant-id' },
|
|
20
|
+
* });
|
|
21
|
+
* builder.setRequiresAuth(true);
|
|
22
|
+
* });
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @module @equinor/fusion-framework-module-msal
|
|
26
|
+
*/
|
|
27
|
+
|
|
1
28
|
export {
|
|
2
29
|
module,
|
|
3
30
|
configureMsal,
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { normalizeUri } from './normalize-uri';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Compares
|
|
4
|
+
* Compares two URIs after normalizing them to their canonical form.
|
|
5
|
+
*
|
|
6
|
+
* Both values are passed through {@link normalizeUri} before comparison, so relative
|
|
7
|
+
* paths, double slashes, and trailing slashes are handled transparently.
|
|
5
8
|
*
|
|
6
9
|
* @internal
|
|
10
|
+
*
|
|
11
|
+
* @param a - First URI or relative path
|
|
12
|
+
* @param b - Second URI or relative path
|
|
13
|
+
* @returns `true` when both URIs resolve to the same normalized string
|
|
7
14
|
*/
|
|
8
15
|
export const compareOrigin = (a: string, b: string): boolean => {
|
|
9
16
|
const url = { a: normalizeUri(a), b: normalizeUri(b) };
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Creates and normalizes redirect
|
|
3
|
-
*
|
|
2
|
+
* Creates and normalizes a redirect URI.
|
|
3
|
+
*
|
|
4
|
+
* Resolves relative paths against the provided base URL and strips double and trailing slashes
|
|
5
|
+
* from the resulting pathname. Used internally to sanitize redirect URIs before passing them
|
|
6
|
+
* to MSAL authentication flows.
|
|
4
7
|
*
|
|
5
8
|
* @internal
|
|
6
9
|
*
|
|
7
|
-
* @param uri -
|
|
8
|
-
* @param home -
|
|
10
|
+
* @param uri - Relative path (e.g. `/callback`) or absolute URL (e.g. `https://app.com/callback`)
|
|
11
|
+
* @param home - Base URL for resolving relative paths. Defaults to `window.location.origin`.
|
|
12
|
+
* @returns Fully-qualified, normalized URI string
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* normalizeUri('/callback'); // https://current-origin.com/callback
|
|
17
|
+
* normalizeUri('https://app.com//callback/'); // https://app.com/callback
|
|
18
|
+
* ```
|
|
9
19
|
*/
|
|
10
20
|
export const normalizeUri = (uri: string, home: string = window.location.origin): string => {
|
|
11
21
|
uri = uri.match(/^http[s]?/) ? uri : home + uri;
|
package/src/util/redirect.ts
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Redirects browser to
|
|
3
|
-
*
|
|
2
|
+
* Redirects the browser to the specified URL.
|
|
3
|
+
*
|
|
4
|
+
* If the browser has not navigated away within the given timeout, the returned
|
|
5
|
+
* promise is rejected. This acts as a safeguard against redirect failures.
|
|
4
6
|
*
|
|
5
7
|
* @internal
|
|
6
8
|
*
|
|
7
|
-
* @param url -
|
|
8
|
-
* @param timeout -
|
|
9
|
-
* @param history -
|
|
9
|
+
* @param url - Endpoint to navigate to
|
|
10
|
+
* @param timeout - Maximum milliseconds to wait before considering the redirect failed. Defaults to `3000`.
|
|
11
|
+
* @param history - When `true`, uses `location.assign()` so the current page is kept in browser history.
|
|
12
|
+
* Otherwise uses `location.replace()` which replaces the current history entry.
|
|
13
|
+
* @returns A promise that rejects after the timeout (it never resolves because a successful redirect
|
|
14
|
+
* causes the page to unload)
|
|
10
15
|
*/
|
|
11
16
|
export const redirect = (url: string, timeout = 3000, history?: boolean): Promise<void> => {
|
|
12
17
|
history ? window.location.assign(url) : window.location.replace(url);
|
|
@@ -4,17 +4,40 @@ import type {
|
|
|
4
4
|
IPublicClientApplication,
|
|
5
5
|
} from './types';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Simplified ID token claims used by the v2 compatibility layer.
|
|
9
|
+
*
|
|
10
|
+
* @property aud - Token audience (application ID)
|
|
11
|
+
* @property exp - Token expiration time (seconds since epoch)
|
|
12
|
+
*/
|
|
7
13
|
export type IdTokenClaims = {
|
|
8
14
|
aud: string;
|
|
9
15
|
exp: number;
|
|
10
16
|
};
|
|
11
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Extended account information for v2 compatibility.
|
|
20
|
+
*
|
|
21
|
+
* Augments the base v2 `AccountInfo` with typed ID token claims.
|
|
22
|
+
*/
|
|
12
23
|
export type AccountInfo = AccountInfoBase & {
|
|
13
24
|
idTokenClaims?: IdTokenClaims;
|
|
14
25
|
};
|
|
15
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Authentication behavior type for v2-compatible login and token flows.
|
|
29
|
+
*
|
|
30
|
+
* - `'popup'` — Opens a popup window for authentication
|
|
31
|
+
* - `'redirect'` — Navigates the browser to the Microsoft login page
|
|
32
|
+
*/
|
|
16
33
|
export type AuthBehavior = 'popup' | 'redirect';
|
|
17
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Simplified authentication request for v2-compatible methods.
|
|
37
|
+
*
|
|
38
|
+
* @property scopes - Optional OAuth scopes to request (e.g. `['User.Read']`)
|
|
39
|
+
* @property loginHint - Optional username hint to pre-fill the login form
|
|
40
|
+
*/
|
|
18
41
|
export type AuthRequest = {
|
|
19
42
|
scopes?: string[];
|
|
20
43
|
loginHint?: string;
|
|
@@ -8,7 +8,17 @@ import type { IAuthClient } from './IAuthClient.interface';
|
|
|
8
8
|
*
|
|
9
9
|
* This interface defines the contract for authentication providers that maintain
|
|
10
10
|
* backward compatibility with MSAL v2 API while using MSAL v4 implementation
|
|
11
|
-
* under the hood.
|
|
11
|
+
* under the hood. Used by the v2 proxy layer during gradual migration scenarios.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* // Obtain a v2 proxy from the current provider
|
|
16
|
+
* const v2Provider: IMsalProvider = provider.createProxyProvider('2.0.0');
|
|
17
|
+
*
|
|
18
|
+
* // Use v2-style API
|
|
19
|
+
* await v2Provider.login();
|
|
20
|
+
* const token = await v2Provider.acquireAccessToken({ scopes: ['User.Read'] });
|
|
21
|
+
* ```
|
|
12
22
|
*/
|
|
13
23
|
export interface IMsalProvider {
|
|
14
24
|
/** Current version of the provider (MSAL module version) */
|
|
@@ -5,22 +5,24 @@ import { mapAuthenticationResult } from './map-authentication-result';
|
|
|
5
5
|
import type { AccountInfo } from './types';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Creates a v2-compatible proxy
|
|
8
|
+
* Creates a v2-compatible proxy wrapper around an MSAL v4 client.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
* and
|
|
10
|
+
* The proxy intercepts property access on the v4 `IMsalClient` and adapts method
|
|
11
|
+
* signatures, return types, and account data to match the v2 `IAuthClient` interface.
|
|
12
|
+
* This allows consumer code written against MSAL v2 to continue working unchanged
|
|
13
|
+
* while the underlying implementation uses MSAL v4/v5.
|
|
12
14
|
*
|
|
13
|
-
* @param client - The MSAL v4
|
|
14
|
-
* @returns A proxy
|
|
15
|
+
* @param client - The MSAL v4 `IMsalClient` instance to wrap
|
|
16
|
+
* @returns A proxy implementing the v2-compatible `IAuthClient` interface
|
|
15
17
|
*
|
|
16
18
|
* @example
|
|
17
19
|
* ```typescript
|
|
18
|
-
* const v4Client = new
|
|
19
|
-
* const v2Client =
|
|
20
|
+
* const v4Client = new MsalClient(config);
|
|
21
|
+
* const v2Client = createProxyClient(v4Client);
|
|
20
22
|
*
|
|
21
23
|
* // Use v2-compatible methods
|
|
22
24
|
* const accounts = v2Client.getAllAccounts();
|
|
23
|
-
* const
|
|
25
|
+
* const result = await v2Client.acquireTokenSilent({ scopes: ['User.Read'], account });
|
|
24
26
|
* ```
|
|
25
27
|
*/
|
|
26
28
|
export function createProxyClient(client: IMsalClient): IAuthClient {
|
|
@@ -2,10 +2,13 @@ import type { AccountInfo } from '@azure/msal-browser';
|
|
|
2
2
|
import type { AccountInfo as AccountInfo_v2 } from './types';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Maps current AccountInfo to v2 AccountInfo format.
|
|
5
|
+
* Maps a current (v4/v5) `AccountInfo` object to the v2-compatible `AccountInfo` format.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Strips properties that don't exist in v2, ensuring backward-compatible serialization
|
|
8
|
+
* and type safety when passing account data through the v2 proxy layer.
|
|
9
|
+
*
|
|
10
|
+
* @param account - The current MSAL v4/v5 `AccountInfo` to convert
|
|
11
|
+
* @returns A v2-compatible `AccountInfo` containing only fields recognised by MSAL v2 consumers
|
|
9
12
|
*/
|
|
10
13
|
export function mapAccountInfo(account: AccountInfo): AccountInfo_v2 {
|
|
11
14
|
return {
|
|
@@ -3,10 +3,14 @@ import type { AuthenticationResult as AuthenticationResult_v2 } from './types';
|
|
|
3
3
|
import { mapAccountInfo } from './map-account-info';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* Maps current AuthenticationResult to v2
|
|
6
|
+
* Maps a current (v4/v5) `AuthenticationResult` to the v2-compatible format.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* Converts the full authentication result — including the nested account object —
|
|
9
|
+
* to the subset of fields that MSAL v2 consumers expect. This enables the v2 proxy
|
|
10
|
+
* layer to return type-safe results without exposing v4/v5-only properties.
|
|
11
|
+
*
|
|
12
|
+
* @param result - The current MSAL v4/v5 `AuthenticationResult` to convert
|
|
13
|
+
* @returns A v2-compatible `AuthenticationResult` with mapped account and token fields
|
|
10
14
|
*/
|
|
11
15
|
export function mapAuthenticationResult(result: AuthenticationResult): AuthenticationResult_v2 {
|
|
12
16
|
return {
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by genversion.
|
|
2
|
-
export const version = '
|
|
2
|
+
export const version = '8.0.0';
|