@equinor/fusion-framework-module-msal 10.0.0 → 10.0.2
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 +16 -0
- package/dist/esm/MsalClient.js +9 -0
- package/dist/esm/MsalClient.js.map +1 -1
- package/dist/esm/MsalConfigurator.js +3 -1
- package/dist/esm/MsalConfigurator.js.map +1 -1
- package/dist/esm/MsalProvider.js +20 -1
- package/dist/esm/MsalProvider.js.map +1 -1
- package/dist/esm/create-client-log-callback.js +1 -0
- package/dist/esm/create-client-log-callback.js.map +1 -1
- package/dist/esm/create-proxy-provider.js +5 -0
- package/dist/esm/create-proxy-provider.js.map +1 -1
- package/dist/esm/module.js +3 -2
- package/dist/esm/module.js.map +1 -1
- package/dist/esm/util/normalize-uri.js.map +1 -1
- package/dist/esm/v2/Logger.js +173 -0
- package/dist/esm/v2/Logger.js.map +1 -0
- package/dist/esm/v2/create-proxy-client.js +6 -0
- package/dist/esm/v2/create-proxy-client.js.map +1 -1
- package/dist/esm/v2/create-proxy-provider.js +4 -0
- package/dist/esm/v2/create-proxy-provider.js.map +1 -1
- package/dist/esm/v2/types.js +3 -124
- package/dist/esm/v2/types.js.map +1 -1
- package/dist/esm/v4/create-proxy-provider.js +1 -0
- package/dist/esm/v4/create-proxy-provider.js.map +1 -1
- package/dist/esm/v4/types.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/versioning/VersionError.js.map +1 -1
- package/dist/esm/versioning/resolve-version.js +4 -0
- package/dist/esm/versioning/resolve-version.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/MsalClient.d.ts +4 -0
- package/dist/types/MsalConfigurator.d.ts +1 -0
- package/dist/types/MsalProvider.d.ts +13 -0
- package/dist/types/create-proxy-provider.d.ts +3 -0
- package/dist/types/static.d.ts +1 -1
- package/dist/types/v2/IAuthClient.interface.d.ts +2 -2
- package/dist/types/v2/Logger.d.ts +92 -0
- package/dist/types/v2/MsalProvider.interface.d.ts +1 -1
- package/dist/types/v2/types.d.ts +3 -49
- package/dist/types/v4/types.d.ts +1 -3
- package/dist/types/version.d.ts +1 -1
- package/package.json +7 -7
- package/src/MsalClient.ts +9 -0
- package/src/MsalConfigurator.ts +3 -1
- package/src/MsalProvider.ts +20 -1
- package/src/create-client-log-callback.ts +1 -0
- package/src/create-proxy-provider.ts +5 -0
- package/src/module.ts +3 -2
- package/src/v2/IAuthClient.interface.ts +2 -2
- package/src/v2/Logger.ts +204 -0
- package/src/v2/MsalProvider.interface.ts +1 -1
- package/src/v2/create-proxy-client.ts +6 -0
- package/src/v2/create-proxy-provider.ts +4 -0
- package/src/v2/types.ts +8 -158
- package/src/v4/create-proxy-provider.ts +1 -0
- package/src/v4/types.ts +3 -3
- package/src/version.ts +1 -1
- package/src/versioning/resolve-version.ts +4 -0
|
@@ -100,6 +100,8 @@ export declare class MsalClient extends PublicClientApplication implements IMsal
|
|
|
100
100
|
* - **Redirect**: Navigates browser to Microsoft login page. Returns `void` because the browser
|
|
101
101
|
* navigates to a new page. After redirect completes, the result will be available via
|
|
102
102
|
* `handleRedirectPromise()` when the app loads on the new page.
|
|
103
|
+
*
|
|
104
|
+
* @throws {Error} If an invalid `options.behavior` value is provided.
|
|
103
105
|
*/
|
|
104
106
|
login(options: Required<LoginOptions>): Promise<LoginResult>;
|
|
105
107
|
/**
|
|
@@ -153,6 +155,8 @@ export declare class MsalClient extends PublicClientApplication implements IMsal
|
|
|
153
155
|
*
|
|
154
156
|
* The default silent behavior is determined by presence of account in the request.
|
|
155
157
|
* This provides optimal UX by minimizing unnecessary user interactions.
|
|
158
|
+
*
|
|
159
|
+
* @throws {Error} If no `request` is provided in `options`.
|
|
156
160
|
*/
|
|
157
161
|
acquireToken(options: AcquireTokenOptions): Promise<AcquireTokenResult>;
|
|
158
162
|
}
|
|
@@ -37,6 +37,8 @@ export declare class MsalProvider extends BaseModuleProvider<MsalConfig> impleme
|
|
|
37
37
|
* Default OAuth scopes used when the caller provides no scopes.
|
|
38
38
|
*
|
|
39
39
|
* Resolves to the app's Entra ID configured permissions via the `/.default` scope.
|
|
40
|
+
*
|
|
41
|
+
* @returns The default OAuth scopes derived from the configured client ID.
|
|
40
42
|
*/
|
|
41
43
|
get defaultScopes(): string[];
|
|
42
44
|
/**
|
|
@@ -54,6 +56,8 @@ export declare class MsalProvider extends BaseModuleProvider<MsalConfig> impleme
|
|
|
54
56
|
*
|
|
55
57
|
* Provides access to the underlying MSAL PublicClientApplication for advanced use cases.
|
|
56
58
|
* Prefer using provider methods for standard authentication operations.
|
|
59
|
+
*
|
|
60
|
+
* @returns The underlying MSAL client instance.
|
|
57
61
|
*/
|
|
58
62
|
get client(): IMsalClient;
|
|
59
63
|
/**
|
|
@@ -61,6 +65,8 @@ export declare class MsalProvider extends BaseModuleProvider<MsalConfig> impleme
|
|
|
61
65
|
*
|
|
62
66
|
* Returns the active account if a user is authenticated, or null if no user is logged in.
|
|
63
67
|
* This is a shorthand for `client.getActiveAccount()`.
|
|
68
|
+
*
|
|
69
|
+
* @returns The currently authenticated account, or `null` if no user is logged in.
|
|
64
70
|
*/
|
|
65
71
|
get account(): AccountInfo | null;
|
|
66
72
|
/**
|
|
@@ -93,6 +99,8 @@ export declare class MsalProvider extends BaseModuleProvider<MsalConfig> impleme
|
|
|
93
99
|
*
|
|
94
100
|
* The provider will attempt automatic login with empty scopes if requiresAuth is true.
|
|
95
101
|
* Apps should call acquireToken with actual scopes after initialization completes.
|
|
102
|
+
*
|
|
103
|
+
* @throws {Error} If auth code exchange requires a client ID but none is configured.
|
|
96
104
|
*/
|
|
97
105
|
initialize(): Promise<void>;
|
|
98
106
|
/**
|
|
@@ -126,6 +134,8 @@ export declare class MsalProvider extends BaseModuleProvider<MsalConfig> impleme
|
|
|
126
134
|
* @remark Empty scopes are currently tracked as telemetry exceptions but execution continues for monitoring purposes.
|
|
127
135
|
* This behavior will be changed to throw exceptions once sufficient metrics are collected.
|
|
128
136
|
*
|
|
137
|
+
* @throws {Error} Re-throws any error encountered during token acquisition after tracking it via telemetry.
|
|
138
|
+
*
|
|
129
139
|
* @example
|
|
130
140
|
* ```typescript
|
|
131
141
|
* // Modern API format
|
|
@@ -257,6 +267,9 @@ export declare class MsalProvider extends BaseModuleProvider<MsalConfig> impleme
|
|
|
257
267
|
* - Version compatibility is tracked via telemetry
|
|
258
268
|
* - Throws error if unsupported version is requested
|
|
259
269
|
*
|
|
270
|
+
* @template T - The provider interface type expected by the target version.
|
|
271
|
+
* @throws {Error} If the requested version cannot be resolved or the proxy fails to create.
|
|
272
|
+
*
|
|
260
273
|
* @example
|
|
261
274
|
* ```typescript
|
|
262
275
|
* // Create v2-compatible proxy
|
|
@@ -10,6 +10,9 @@ import type { IMsalProvider } from './MsalProvider.interface';
|
|
|
10
10
|
* @param version - The target version string (e.g., '2.0.0', '4.0.0')
|
|
11
11
|
* @returns A proxy provider compatible with the specified version
|
|
12
12
|
*
|
|
13
|
+
* @template T - The provider interface type expected by the target version.
|
|
14
|
+
* @throws {Error} If the resolved version is not supported.
|
|
15
|
+
*
|
|
13
16
|
* @example
|
|
14
17
|
* ```typescript
|
|
15
18
|
* const baseProvider = new MsalProvider(config);
|
package/dist/types/static.d.ts
CHANGED
|
@@ -79,7 +79,7 @@ export interface IAuthClient extends IPublicClientApplication {
|
|
|
79
79
|
* @param silent - Whether to attempt silent authentication first
|
|
80
80
|
* @returns Promise resolving to authentication result or void
|
|
81
81
|
*/
|
|
82
|
-
login(options?: AuthRequest, behavior?: AuthBehavior, silent?: boolean): Promise<AuthenticationResult |
|
|
82
|
+
login(options?: AuthRequest, behavior?: AuthBehavior, silent?: boolean): Promise<AuthenticationResult | undefined>;
|
|
83
83
|
/**
|
|
84
84
|
* Acquire access token with optional silent authentication fallback
|
|
85
85
|
* @param options - Authentication request options
|
|
@@ -87,5 +87,5 @@ export interface IAuthClient extends IPublicClientApplication {
|
|
|
87
87
|
* @param silent - Whether to attempt silent authentication first
|
|
88
88
|
* @returns Promise resolving to authentication result or void
|
|
89
89
|
*/
|
|
90
|
-
acquireToken(options?: AuthRequest, behavior?: AuthBehavior, silent?: boolean): Promise<AuthenticationResult |
|
|
90
|
+
acquireToken(options?: AuthRequest, behavior?: AuthBehavior, silent?: boolean): Promise<AuthenticationResult | undefined>;
|
|
91
91
|
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { LogLevel, type LoggerOptions } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Class which facilitates logging of messages to a specific place
|
|
4
|
+
*/
|
|
5
|
+
export declare class Logger {
|
|
6
|
+
private correlationId;
|
|
7
|
+
private level;
|
|
8
|
+
private piiLoggingEnabled;
|
|
9
|
+
private localCallback;
|
|
10
|
+
private packageName;
|
|
11
|
+
private packageVersion;
|
|
12
|
+
/**
|
|
13
|
+
* Creates a new `Logger`.
|
|
14
|
+
*
|
|
15
|
+
* @param loggerOptions - Logger configuration, including callback, PII, and log level settings.
|
|
16
|
+
* @param packageName - Name of the package implementing this logger.
|
|
17
|
+
* @param packageVersion - Version of the package implementing this logger.
|
|
18
|
+
*/
|
|
19
|
+
constructor(loggerOptions: LoggerOptions, packageName?: string, packageVersion?: string);
|
|
20
|
+
/**
|
|
21
|
+
* Creates the default logger options used when none are provided.
|
|
22
|
+
*
|
|
23
|
+
* @returns Default logger options with a no-op callback, PII logging disabled, and Info level.
|
|
24
|
+
*/
|
|
25
|
+
private static createDefaultLoggerOptions;
|
|
26
|
+
/**
|
|
27
|
+
* Create new Logger with existing configurations.
|
|
28
|
+
*
|
|
29
|
+
* @param packageName - Name of the package implementing this logger.
|
|
30
|
+
* @param packageVersion - Version of the package implementing this logger.
|
|
31
|
+
* @param correlationId - Correlation ID to use, falling back to this logger's own if omitted.
|
|
32
|
+
* @returns A new `Logger` instance cloned from this one.
|
|
33
|
+
*/
|
|
34
|
+
clone(packageName: string, packageVersion: string, correlationId?: string): Logger;
|
|
35
|
+
/**
|
|
36
|
+
* Logs error messages.
|
|
37
|
+
*
|
|
38
|
+
* @param message - The message to log.
|
|
39
|
+
* @param correlationId - Correlation ID to attach to the log entry, if any.
|
|
40
|
+
*/
|
|
41
|
+
error(message: string, correlationId?: string): void;
|
|
42
|
+
/**
|
|
43
|
+
* Logs warning messages.
|
|
44
|
+
*
|
|
45
|
+
* @param message - The message to log.
|
|
46
|
+
* @param correlationId - Correlation ID to attach to the log entry, if any.
|
|
47
|
+
*/
|
|
48
|
+
warning(message: string, correlationId?: string): void;
|
|
49
|
+
/**
|
|
50
|
+
* Logs info messages.
|
|
51
|
+
*
|
|
52
|
+
* @param message - The message to log.
|
|
53
|
+
* @param correlationId - Correlation ID to attach to the log entry, if any.
|
|
54
|
+
*/
|
|
55
|
+
info(message: string, correlationId?: string): void;
|
|
56
|
+
/**
|
|
57
|
+
* Logs verbose messages.
|
|
58
|
+
*
|
|
59
|
+
* @param message - The message to log.
|
|
60
|
+
* @param correlationId - Correlation ID to attach to the log entry, if any.
|
|
61
|
+
*/
|
|
62
|
+
verbose(message: string, correlationId?: string): void;
|
|
63
|
+
/**
|
|
64
|
+
* Logs trace messages.
|
|
65
|
+
*
|
|
66
|
+
* @param message - The message to log.
|
|
67
|
+
* @param correlationId - Correlation ID to attach to the log entry, if any.
|
|
68
|
+
*/
|
|
69
|
+
trace(message: string, correlationId?: string): void;
|
|
70
|
+
/**
|
|
71
|
+
* Returns whether PII Logging is enabled or not.
|
|
72
|
+
*
|
|
73
|
+
* @returns `true` when PII logging is enabled, otherwise `false`.
|
|
74
|
+
*/
|
|
75
|
+
isPiiLoggingEnabled(): boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Formats and dispatches a log message to the configured callback, unless it
|
|
78
|
+
* is below the configured log level or contains PII while PII logging is disabled.
|
|
79
|
+
*
|
|
80
|
+
* @param logMessage - The raw message to log.
|
|
81
|
+
* @param options - Log level, PII flag, and correlation ID for this message.
|
|
82
|
+
*/
|
|
83
|
+
private logMessage;
|
|
84
|
+
/**
|
|
85
|
+
* Execute callback with message.
|
|
86
|
+
*
|
|
87
|
+
* @param level - The log level of the message.
|
|
88
|
+
* @param message - The formatted message to send to the callback.
|
|
89
|
+
* @param containsPii - Whether the message contains personally identifiable information.
|
|
90
|
+
*/
|
|
91
|
+
executeCallback(level: LogLevel, message: string, containsPii: boolean): void;
|
|
92
|
+
}
|
|
@@ -81,7 +81,7 @@ export interface IMsalProvider {
|
|
|
81
81
|
/**
|
|
82
82
|
* Handle authentication redirect
|
|
83
83
|
*/
|
|
84
|
-
handleRedirect(): Promise<
|
|
84
|
+
handleRedirect(): Promise<undefined | null>;
|
|
85
85
|
/**
|
|
86
86
|
* Create a proxy provider for version compatibility
|
|
87
87
|
* @param version - Version string
|
package/dist/types/v2/types.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* This file contains all types required to type IPublicClientApplication
|
|
5
5
|
* from MSAL v2.38.4 to maintain backward compatibility while using MSAL v4 implementation.
|
|
6
6
|
*/
|
|
7
|
+
import type { Logger } from './Logger.js';
|
|
7
8
|
/**
|
|
8
9
|
* Key-Value type to support queryParams, extraQueryParams and claims
|
|
9
10
|
*/
|
|
@@ -291,9 +292,7 @@ export declare enum LogLevel {
|
|
|
291
292
|
/**
|
|
292
293
|
* Callback to send the messages to
|
|
293
294
|
*/
|
|
294
|
-
export
|
|
295
|
-
(level: LogLevel, message: string, containsPii: boolean): void;
|
|
296
|
-
}
|
|
295
|
+
export type ILoggerCallback = (level: LogLevel, message: string, containsPii: boolean) => void;
|
|
297
296
|
/**
|
|
298
297
|
* Options for logger messages
|
|
299
298
|
*/
|
|
@@ -303,52 +302,7 @@ export type LoggerOptions = {
|
|
|
303
302
|
logLevel?: LogLevel;
|
|
304
303
|
correlationId?: string;
|
|
305
304
|
};
|
|
306
|
-
|
|
307
|
-
* Class which facilitates logging of messages to a specific place
|
|
308
|
-
*/
|
|
309
|
-
export declare class Logger {
|
|
310
|
-
private correlationId;
|
|
311
|
-
private level;
|
|
312
|
-
private piiLoggingEnabled;
|
|
313
|
-
private localCallback;
|
|
314
|
-
private packageName;
|
|
315
|
-
private packageVersion;
|
|
316
|
-
constructor(loggerOptions: LoggerOptions, packageName?: string, packageVersion?: string);
|
|
317
|
-
private static createDefaultLoggerOptions;
|
|
318
|
-
/**
|
|
319
|
-
* Create new Logger with existing configurations.
|
|
320
|
-
*/
|
|
321
|
-
clone(packageName: string, packageVersion: string, correlationId?: string): Logger;
|
|
322
|
-
/**
|
|
323
|
-
* Logs error messages.
|
|
324
|
-
*/
|
|
325
|
-
error(message: string, correlationId?: string): void;
|
|
326
|
-
/**
|
|
327
|
-
* Logs warning messages.
|
|
328
|
-
*/
|
|
329
|
-
warning(message: string, correlationId?: string): void;
|
|
330
|
-
/**
|
|
331
|
-
* Logs info messages.
|
|
332
|
-
*/
|
|
333
|
-
info(message: string, correlationId?: string): void;
|
|
334
|
-
/**
|
|
335
|
-
* Logs verbose messages.
|
|
336
|
-
*/
|
|
337
|
-
verbose(message: string, correlationId?: string): void;
|
|
338
|
-
/**
|
|
339
|
-
* Logs trace messages.
|
|
340
|
-
*/
|
|
341
|
-
trace(message: string, correlationId?: string): void;
|
|
342
|
-
/**
|
|
343
|
-
* Returns whether PII Logging is enabled or not.
|
|
344
|
-
*/
|
|
345
|
-
isPiiLoggingEnabled(): boolean;
|
|
346
|
-
private logMessage;
|
|
347
|
-
/**
|
|
348
|
-
* Execute callback with message.
|
|
349
|
-
*/
|
|
350
|
-
executeCallback(level: LogLevel, message: string, containsPii: boolean): void;
|
|
351
|
-
}
|
|
305
|
+
export { Logger } from './Logger.js';
|
|
352
306
|
/**
|
|
353
307
|
* Performance event type
|
|
354
308
|
*/
|
package/dist/types/v4/types.d.ts
CHANGED
|
@@ -395,9 +395,7 @@ export declare enum LogLevel {
|
|
|
395
395
|
/**
|
|
396
396
|
* Callback to send the messages to
|
|
397
397
|
*/
|
|
398
|
-
export
|
|
399
|
-
(level: LogLevel, message: string, containsPii: boolean): void;
|
|
400
|
-
}
|
|
398
|
+
export type ILoggerCallback = (level: LogLevel, message: string, containsPii: boolean) => void;
|
|
401
399
|
/**
|
|
402
400
|
* Event callback function type
|
|
403
401
|
*/
|
package/dist/types/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "10.0.
|
|
1
|
+
export declare const version = "10.0.2";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@equinor/fusion-framework-module-msal",
|
|
3
|
-
"version": "10.0.
|
|
3
|
+
"version": "10.0.2",
|
|
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",
|
|
@@ -48,18 +48,18 @@
|
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/semver": "^7.7.1",
|
|
50
50
|
"semver": "^7.7.4",
|
|
51
|
-
"typescript": "^
|
|
51
|
+
"typescript": "^7.0.2",
|
|
52
52
|
"zod": "^4.4.3",
|
|
53
|
-
"@equinor/fusion-framework-module": "^6.1.
|
|
54
|
-
"@equinor/fusion-framework-module-telemetry": "^7.0.
|
|
53
|
+
"@equinor/fusion-framework-module": "^6.1.1",
|
|
54
|
+
"@equinor/fusion-framework-module-telemetry": "^7.0.1"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"@types/semver": "^7.0.0",
|
|
58
58
|
"semver": "^7.0.0",
|
|
59
|
-
"typescript": "
|
|
59
|
+
"typescript": ">=5.0.0",
|
|
60
60
|
"zod": "^4.0.0",
|
|
61
|
-
"@equinor/fusion-framework-module": "^6.1.
|
|
62
|
-
"@equinor/fusion-framework-module-telemetry": "^7.0.
|
|
61
|
+
"@equinor/fusion-framework-module": "^6.1.1",
|
|
62
|
+
"@equinor/fusion-framework-module-telemetry": "^7.0.1"
|
|
63
63
|
},
|
|
64
64
|
"peerDependenciesMeta": {
|
|
65
65
|
"@equinor/fusion-framework-module-telemetry": {
|
package/src/MsalClient.ts
CHANGED
|
@@ -145,11 +145,14 @@ export class MsalClient extends PublicClientApplication implements IMsalClient {
|
|
|
145
145
|
* - **Redirect**: Navigates browser to Microsoft login page. Returns `void` because the browser
|
|
146
146
|
* navigates to a new page. After redirect completes, the result will be available via
|
|
147
147
|
* `handleRedirectPromise()` when the app loads on the new page.
|
|
148
|
+
*
|
|
149
|
+
* @throws {Error} If an invalid `options.behavior` value is provided.
|
|
148
150
|
*/
|
|
149
151
|
async login(options: Required<LoginOptions>): Promise<LoginResult> {
|
|
150
152
|
// Attempt silent authentication first if enabled
|
|
151
153
|
// This provides better UX by avoiding unnecessary popups/redirects
|
|
152
154
|
if (options.silent) {
|
|
155
|
+
// Warn early when neither an account nor login hint is available for silent SSO
|
|
153
156
|
if (!options.request.account && !options.request.loginHint) {
|
|
154
157
|
this.getLogger().warning(
|
|
155
158
|
'No account or login hint provided, please provide an account or login hint in the request',
|
|
@@ -216,6 +219,7 @@ export class MsalClient extends PublicClientApplication implements IMsalClient {
|
|
|
216
219
|
* ```
|
|
217
220
|
*/
|
|
218
221
|
async logout(options?: LogoutOptions): Promise<void> {
|
|
222
|
+
// Warn when no account was supplied since the active account will be used instead
|
|
219
223
|
if (!options?.account) {
|
|
220
224
|
this.getLogger().warning(
|
|
221
225
|
'No account available for logout, please provide an account in the options',
|
|
@@ -253,14 +257,18 @@ export class MsalClient extends PublicClientApplication implements IMsalClient {
|
|
|
253
257
|
*
|
|
254
258
|
* The default silent behavior is determined by presence of account in the request.
|
|
255
259
|
* This provides optimal UX by minimizing unnecessary user interactions.
|
|
260
|
+
*
|
|
261
|
+
* @throws {Error} If no `request` is provided in `options`.
|
|
256
262
|
*/
|
|
257
263
|
async acquireToken(options: AcquireTokenOptions): Promise<AcquireTokenResult> {
|
|
258
264
|
const { behavior = 'redirect', silent = !!options.request?.account, request } = options;
|
|
259
265
|
|
|
266
|
+
// A request is required to know which scopes/account to acquire a token for
|
|
260
267
|
if (!request) {
|
|
261
268
|
throw new Error('No request provided, please provide a request in the options');
|
|
262
269
|
}
|
|
263
270
|
|
|
271
|
+
// Warn when no scopes are requested, since MSAL requires at least one scope
|
|
264
272
|
if (request.scopes.length === 0) {
|
|
265
273
|
this.getLogger().warning(
|
|
266
274
|
'No scopes provided, please provide scopes in the request option, see options.request for more information.',
|
|
@@ -271,6 +279,7 @@ export class MsalClient extends PublicClientApplication implements IMsalClient {
|
|
|
271
279
|
// Attempt silent token acquisition first
|
|
272
280
|
// This fetches from cache or uses refresh token without user interaction
|
|
273
281
|
if (silent) {
|
|
282
|
+
// Only silent-acquire when an account is available to look up cached tokens for
|
|
274
283
|
if (request.account) {
|
|
275
284
|
try {
|
|
276
285
|
this.getLogger().verbose(
|
package/src/MsalConfigurator.ts
CHANGED
|
@@ -84,6 +84,7 @@ export class MsalConfigurator extends BaseConfigBuilder<MsalConfig> {
|
|
|
84
84
|
* The MSAL module version being configured.
|
|
85
85
|
*
|
|
86
86
|
* @default Latest
|
|
87
|
+
* @returns The configured MSAL module version.
|
|
87
88
|
*/
|
|
88
89
|
public get version(): string {
|
|
89
90
|
return version;
|
|
@@ -100,6 +101,7 @@ export class MsalConfigurator extends BaseConfigBuilder<MsalConfig> {
|
|
|
100
101
|
this._set('version', async () => this.version);
|
|
101
102
|
// Auto-detect and integrate telemetry module if available
|
|
102
103
|
this._set('telemetry.provider', async (args) => {
|
|
104
|
+
// Only resolve the telemetry instance when the telemetry module is registered
|
|
103
105
|
if (args.hasModule('telemetry')) {
|
|
104
106
|
const telemetry = await args.requireInstance('telemetry');
|
|
105
107
|
return telemetry;
|
|
@@ -335,7 +337,7 @@ export class MsalConfigurator extends BaseConfigBuilder<MsalConfig> {
|
|
|
335
337
|
|
|
336
338
|
// Auto-create client if config provided but no client instance
|
|
337
339
|
// This allows users to provide configuration without manually instantiating the client
|
|
338
|
-
if (!config.client &&
|
|
340
|
+
if (!config.client && this.#msalConfig) {
|
|
339
341
|
const clientConfig = this.#msalConfig;
|
|
340
342
|
|
|
341
343
|
config.telemetry.provider?.trackEvent({
|
package/src/MsalProvider.ts
CHANGED
|
@@ -67,6 +67,8 @@ export class MsalProvider extends BaseModuleProvider<MsalConfig> implements IMsa
|
|
|
67
67
|
* Default OAuth scopes used when the caller provides no scopes.
|
|
68
68
|
*
|
|
69
69
|
* Resolves to the app's Entra ID configured permissions via the `/.default` scope.
|
|
70
|
+
*
|
|
71
|
+
* @returns The default OAuth scopes derived from the configured client ID.
|
|
70
72
|
*/
|
|
71
73
|
get defaultScopes(): string[] {
|
|
72
74
|
const clientId = this.#client.clientId;
|
|
@@ -91,6 +93,8 @@ export class MsalProvider extends BaseModuleProvider<MsalConfig> implements IMsa
|
|
|
91
93
|
*
|
|
92
94
|
* Provides access to the underlying MSAL PublicClientApplication for advanced use cases.
|
|
93
95
|
* Prefer using provider methods for standard authentication operations.
|
|
96
|
+
*
|
|
97
|
+
* @returns The underlying MSAL client instance.
|
|
94
98
|
*/
|
|
95
99
|
get client(): IMsalClient {
|
|
96
100
|
return this.#client;
|
|
@@ -101,6 +105,8 @@ export class MsalProvider extends BaseModuleProvider<MsalConfig> implements IMsa
|
|
|
101
105
|
*
|
|
102
106
|
* Returns the active account if a user is authenticated, or null if no user is logged in.
|
|
103
107
|
* This is a shorthand for `client.getActiveAccount()`.
|
|
108
|
+
*
|
|
109
|
+
* @returns The currently authenticated account, or `null` if no user is logged in.
|
|
104
110
|
*/
|
|
105
111
|
get account(): AccountInfo | null {
|
|
106
112
|
return this.#client.getActiveAccount();
|
|
@@ -175,6 +181,8 @@ export class MsalProvider extends BaseModuleProvider<MsalConfig> implements IMsa
|
|
|
175
181
|
*
|
|
176
182
|
* The provider will attempt automatic login with empty scopes if requiresAuth is true.
|
|
177
183
|
* Apps should call acquireToken with actual scopes after initialization completes.
|
|
184
|
+
*
|
|
185
|
+
* @throws {Error} If auth code exchange requires a client ID but none is configured.
|
|
178
186
|
*/
|
|
179
187
|
async initialize(): Promise<void> {
|
|
180
188
|
// Guard: skip authentication when running inside MSAL's hidden iframe.
|
|
@@ -204,6 +212,7 @@ export class MsalProvider extends BaseModuleProvider<MsalConfig> implements IMsa
|
|
|
204
212
|
// Use MSAL's acquireTokenByCode to exchange backend auth code for tokens
|
|
205
213
|
// This follows Microsoft's standard SPA Auth Code Flow pattern
|
|
206
214
|
const clientId = this.#client.clientId;
|
|
215
|
+
// A client ID is required to build the default scope used for the auth code exchange
|
|
207
216
|
if (!clientId) {
|
|
208
217
|
throw new Error('Client ID is required for auth code exchange');
|
|
209
218
|
}
|
|
@@ -248,6 +257,7 @@ export class MsalProvider extends BaseModuleProvider<MsalConfig> implements IMsa
|
|
|
248
257
|
// Priority 1: Check if returning from redirect-based authentication
|
|
249
258
|
// This handles cases where user just completed a login/acquireToken via redirect
|
|
250
259
|
const handleRedirectResult = await this.handleRedirect();
|
|
260
|
+
// A returned account means the user just completed a redirect-based login
|
|
251
261
|
if (handleRedirectResult?.account) {
|
|
252
262
|
// Successfully authenticated via redirect - set as active account
|
|
253
263
|
// This means the user was redirected to Microsoft and came back authenticated
|
|
@@ -263,6 +273,7 @@ export class MsalProvider extends BaseModuleProvider<MsalConfig> implements IMsa
|
|
|
263
273
|
// Note: Using default scopes here as we don't know what scopes the app needs yet
|
|
264
274
|
// App should call acquireToken with actual scopes after initialization
|
|
265
275
|
const loginResult = await this.login({ request: { scopes: this.defaultScopes } });
|
|
276
|
+
// Only set the active account when the automatic login actually returned one
|
|
266
277
|
if (loginResult?.account) {
|
|
267
278
|
// Automatic login successful - set as active account
|
|
268
279
|
this.#client.setActiveAccount(loginResult.account);
|
|
@@ -315,6 +326,8 @@ export class MsalProvider extends BaseModuleProvider<MsalConfig> implements IMsa
|
|
|
315
326
|
* @remark Empty scopes are currently tracked as telemetry exceptions but execution continues for monitoring purposes.
|
|
316
327
|
* This behavior will be changed to throw exceptions once sufficient metrics are collected.
|
|
317
328
|
*
|
|
329
|
+
* @throws {Error} Re-throws any error encountered during token acquisition after tracking it via telemetry.
|
|
330
|
+
*
|
|
318
331
|
* @example
|
|
319
332
|
* ```typescript
|
|
320
333
|
* // Modern API format
|
|
@@ -371,6 +384,7 @@ export class MsalProvider extends BaseModuleProvider<MsalConfig> implements IMsa
|
|
|
371
384
|
|
|
372
385
|
// Handle empty scopes - currently monitoring for telemetry, will throw in future
|
|
373
386
|
if (candidateScopes.length === 0) {
|
|
387
|
+
// Fall back to the client-id-derived default scope when one is available
|
|
374
388
|
if (defaultScopes.length > 0) {
|
|
375
389
|
this._trackEvent('acquireToken.missing-scope.defaulted', TelemetryLevel.Warning, {
|
|
376
390
|
properties: { ...telemetryProperties, defaultScopes },
|
|
@@ -383,7 +397,7 @@ export class MsalProvider extends BaseModuleProvider<MsalConfig> implements IMsa
|
|
|
383
397
|
exception,
|
|
384
398
|
properties: telemetryProperties,
|
|
385
399
|
});
|
|
386
|
-
// TODO: throw exception when sufficient metrics are collected
|
|
400
|
+
// TODO(#5113): throw exception when sufficient metrics are collected
|
|
387
401
|
// This allows us to monitor how often empty scopes are provided before enforcing validation
|
|
388
402
|
}
|
|
389
403
|
}
|
|
@@ -521,6 +535,7 @@ export class MsalProvider extends BaseModuleProvider<MsalConfig> implements IMsa
|
|
|
521
535
|
}
|
|
522
536
|
}
|
|
523
537
|
|
|
538
|
+
// Perform interactive authentication based on specified behavior
|
|
524
539
|
switch (behavior) {
|
|
525
540
|
case 'popup':
|
|
526
541
|
return await this.#client.loginPopup(request);
|
|
@@ -606,6 +621,7 @@ export class MsalProvider extends BaseModuleProvider<MsalConfig> implements IMsa
|
|
|
606
621
|
async handleRedirect(): Promise<AuthenticationResult | null> {
|
|
607
622
|
// Process any pending redirect from authentication flow
|
|
608
623
|
const result = await this.client.handleRedirectPromise();
|
|
624
|
+
// Only track/log when a redirect result is actually returned
|
|
609
625
|
if (result) {
|
|
610
626
|
// Track successful redirect completion for monitoring
|
|
611
627
|
this._trackEvent('handleRedirect.success', TelemetryLevel.Information, {
|
|
@@ -632,6 +648,9 @@ export class MsalProvider extends BaseModuleProvider<MsalConfig> implements IMsa
|
|
|
632
648
|
* - Version compatibility is tracked via telemetry
|
|
633
649
|
* - Throws error if unsupported version is requested
|
|
634
650
|
*
|
|
651
|
+
* @template T - The provider interface type expected by the target version.
|
|
652
|
+
* @throws {Error} If the requested version cannot be resolved or the proxy fails to create.
|
|
653
|
+
*
|
|
635
654
|
* @example
|
|
636
655
|
* ```typescript
|
|
637
656
|
* // Create v2-compatible proxy
|
|
@@ -32,6 +32,7 @@ const parseMsalMessage = (message: string) => {
|
|
|
32
32
|
/^\[([^\]]+)\]\s*:\s*\[([^\]]*)\]\s*:\s*([^:]+)\s*:\s*(\w+)\s*-\s*([^-]+)\s*-\s*(.*)$/,
|
|
33
33
|
);
|
|
34
34
|
|
|
35
|
+
// A structured match means we can extract package/component/message parts
|
|
35
36
|
if (match) {
|
|
36
37
|
const [, _timestamp, _correlationId, packageInfo, _logLevel, component, logMessage] = match;
|
|
37
38
|
return {
|
|
@@ -15,6 +15,9 @@ import { createProxyProvider as createProxyProvider_v4 } from './v4/create-proxy
|
|
|
15
15
|
* @param version - The target version string (e.g., '2.0.0', '4.0.0')
|
|
16
16
|
* @returns A proxy provider compatible with the specified version
|
|
17
17
|
*
|
|
18
|
+
* @template T - The provider interface type expected by the target version.
|
|
19
|
+
* @throws {Error} If the resolved version is not supported.
|
|
20
|
+
*
|
|
18
21
|
* @example
|
|
19
22
|
* ```typescript
|
|
20
23
|
* const baseProvider = new MsalProvider(config);
|
|
@@ -28,6 +31,7 @@ export function createProxyProvider<T = IMsalProvider>(
|
|
|
28
31
|
// Resolve the requested version to determine which proxy to create
|
|
29
32
|
const { enumVersion } = resolveVersion(version);
|
|
30
33
|
|
|
34
|
+
// Build the version-appropriate proxy based on the resolved MSAL module version
|
|
31
35
|
switch (enumVersion) {
|
|
32
36
|
case MsalModuleVersion.V2:
|
|
33
37
|
// Create v2-compatible proxy with legacy API adapters
|
|
@@ -39,6 +43,7 @@ export function createProxyProvider<T = IMsalProvider>(
|
|
|
39
43
|
// Create transparent proxy for v5 - passes through to original provider
|
|
40
44
|
return new Proxy(provider, {
|
|
41
45
|
get: (target: IMsalProvider, prop: keyof IMsalProvider) => {
|
|
46
|
+
// Delegate every known property/method to the underlying provider
|
|
42
47
|
switch (prop) {
|
|
43
48
|
case 'version': {
|
|
44
49
|
return target.version;
|
package/src/module.ts
CHANGED
|
@@ -45,6 +45,7 @@ export const module: MsalModule = {
|
|
|
45
45
|
// Priority 2: Check if provider exists in parent module (proxy compatibility)
|
|
46
46
|
// This allows child applications to reuse parent's authentication provider
|
|
47
47
|
const hostProvider = init.ref?.auth;
|
|
48
|
+
// Reuse the parent's provider (via a version-compatible proxy) when available
|
|
48
49
|
if (hostProvider) {
|
|
49
50
|
try {
|
|
50
51
|
const proxyProvider = hostProvider.createProxyProvider(config.version);
|
|
@@ -52,7 +53,7 @@ export const module: MsalModule = {
|
|
|
52
53
|
} catch (error) {
|
|
53
54
|
console.error('MsalModule::Failed to create proxy provider', error);
|
|
54
55
|
// Fallback to host provider to prevent app breakage during migration
|
|
55
|
-
// TODO: Consider throwing error instead once all apps are migrated to v4
|
|
56
|
+
// TODO(#5114): Consider throwing error instead once all apps are migrated to v4
|
|
56
57
|
return hostProvider;
|
|
57
58
|
}
|
|
58
59
|
}
|
|
@@ -105,7 +106,7 @@ export type AuthConfigFn<TRef = unknown> = (
|
|
|
105
106
|
* ```
|
|
106
107
|
*/
|
|
107
108
|
export const enableMSAL = (
|
|
108
|
-
//
|
|
109
|
+
// biome-ignore lint/suspicious/noExplicitAny: must be any to support all module types
|
|
109
110
|
configurator: IModulesConfigurator<any, any>,
|
|
110
111
|
configure?: AuthConfigFn,
|
|
111
112
|
): void => {
|
|
@@ -97,7 +97,7 @@ export interface IAuthClient extends IPublicClientApplication {
|
|
|
97
97
|
options?: AuthRequest,
|
|
98
98
|
behavior?: AuthBehavior,
|
|
99
99
|
silent?: boolean,
|
|
100
|
-
): Promise<AuthenticationResult |
|
|
100
|
+
): Promise<AuthenticationResult | undefined>;
|
|
101
101
|
|
|
102
102
|
/**
|
|
103
103
|
* Acquire access token with optional silent authentication fallback
|
|
@@ -110,5 +110,5 @@ export interface IAuthClient extends IPublicClientApplication {
|
|
|
110
110
|
options?: AuthRequest,
|
|
111
111
|
behavior?: AuthBehavior,
|
|
112
112
|
silent?: boolean,
|
|
113
|
-
): Promise<AuthenticationResult |
|
|
113
|
+
): Promise<AuthenticationResult | undefined>;
|
|
114
114
|
}
|