@equinor/fusion-framework-module-msal 5.1.1 → 6.0.0-next.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.
Files changed (144) hide show
  1. package/CHANGELOG.md +109 -0
  2. package/README.md +237 -40
  3. package/dist/esm/MsalClient.interface.js +2 -0
  4. package/dist/esm/MsalClient.interface.js.map +1 -0
  5. package/dist/esm/MsalClient.js +215 -0
  6. package/dist/esm/MsalClient.js.map +1 -0
  7. package/dist/esm/MsalConfigurator.js +248 -0
  8. package/dist/esm/MsalConfigurator.js.map +1 -0
  9. package/dist/esm/MsalProvider.interface.js +2 -0
  10. package/dist/esm/MsalProvider.interface.js.map +1 -0
  11. package/dist/esm/MsalProvider.js +525 -0
  12. package/dist/esm/MsalProvider.js.map +1 -0
  13. package/dist/esm/MsalProxyProvider.interface.js +2 -0
  14. package/dist/esm/MsalProxyProvider.interface.js.map +1 -0
  15. package/dist/esm/__tests__/versioning/resolve-version.test.js +29 -38
  16. package/dist/esm/__tests__/versioning/resolve-version.test.js.map +1 -1
  17. package/dist/esm/create-client-log-callback.js +87 -0
  18. package/dist/esm/create-client-log-callback.js.map +1 -0
  19. package/dist/esm/create-proxy-provider.js +84 -0
  20. package/dist/esm/create-proxy-provider.js.map +1 -0
  21. package/dist/esm/index.js +1 -1
  22. package/dist/esm/index.js.map +1 -1
  23. package/dist/esm/module.js +64 -16
  24. package/dist/esm/module.js.map +1 -1
  25. package/dist/esm/static.js +32 -2
  26. package/dist/esm/static.js.map +1 -1
  27. package/dist/esm/types.js +9 -0
  28. package/dist/esm/types.js.map +1 -1
  29. package/dist/esm/util/compare-origin.js +11 -0
  30. package/dist/esm/util/compare-origin.js.map +1 -0
  31. package/dist/esm/{v2/client/util/url.js → util/normalize-uri.js} +1 -10
  32. package/dist/esm/util/normalize-uri.js.map +1 -0
  33. package/dist/esm/{v2/client/util/browser.js → util/redirect.js} +1 -1
  34. package/dist/esm/util/redirect.js.map +1 -0
  35. package/dist/esm/v2/IAuthClient.interface.js +2 -0
  36. package/dist/esm/v2/IAuthClient.interface.js.map +1 -0
  37. package/dist/esm/v2/IPublicClientApplication.interface.js +2 -0
  38. package/dist/esm/v2/IPublicClientApplication.interface.js.map +1 -0
  39. package/dist/esm/v2/MsalProvider.interface.js +2 -0
  40. package/dist/esm/v2/MsalProvider.interface.js.map +1 -0
  41. package/dist/esm/v2/create-proxy-client.js +155 -0
  42. package/dist/esm/v2/create-proxy-client.js.map +1 -0
  43. package/dist/esm/v2/create-proxy-provider.js +140 -0
  44. package/dist/esm/v2/create-proxy-provider.js.map +1 -0
  45. package/dist/esm/v2/map-account-info.js +18 -0
  46. package/dist/esm/v2/map-account-info.js.map +1 -0
  47. package/dist/esm/v2/map-authentication-result.js +22 -0
  48. package/dist/esm/v2/map-authentication-result.js.map +1 -0
  49. package/dist/esm/version.js +1 -1
  50. package/dist/esm/version.js.map +1 -1
  51. package/dist/esm/versioning/resolve-version.js +28 -16
  52. package/dist/esm/versioning/resolve-version.js.map +1 -1
  53. package/dist/tsconfig.tsbuildinfo +1 -1
  54. package/dist/types/MsalClient.d.ts +141 -0
  55. package/dist/types/MsalClient.interface.d.ts +103 -0
  56. package/dist/types/MsalConfigurator.d.ts +147 -0
  57. package/dist/types/MsalProvider.d.ts +291 -0
  58. package/dist/types/MsalProvider.interface.d.ts +159 -0
  59. package/dist/types/MsalProxyProvider.interface.d.ts +52 -0
  60. package/dist/types/create-client-log-callback.d.ts +38 -0
  61. package/dist/types/create-proxy-provider.d.ts +19 -0
  62. package/dist/types/index.d.ts +5 -4
  63. package/dist/types/module.d.ts +70 -4
  64. package/dist/types/static.d.ts +32 -1
  65. package/dist/types/types.d.ts +14 -6
  66. package/dist/types/util/redirect.d.ts +1 -0
  67. package/dist/types/v2/IAuthClient.interface.d.ts +68 -0
  68. package/dist/types/v2/IPublicClientApplication.interface.d.ts +68 -0
  69. package/dist/types/v2/MsalProvider.interface.d.ts +85 -0
  70. package/dist/types/v2/create-proxy-client.d.ts +22 -0
  71. package/dist/types/v2/create-proxy-provider.d.ts +24 -0
  72. package/dist/types/v2/map-account-info.d.ts +9 -0
  73. package/dist/types/v2/map-authentication-result.d.ts +9 -0
  74. package/dist/types/v2/types.d.ts +12 -0
  75. package/dist/types/version.d.ts +1 -1
  76. package/dist/types/versioning/resolve-version.d.ts +1 -1
  77. package/package.json +11 -6
  78. package/src/MsalClient.interface.ts +121 -0
  79. package/src/MsalClient.ts +274 -0
  80. package/src/MsalConfigurator.ts +289 -0
  81. package/src/MsalProvider.interface.ts +175 -0
  82. package/src/MsalProvider.ts +597 -0
  83. package/src/MsalProxyProvider.interface.ts +71 -0
  84. package/src/__tests__/versioning/resolve-version.test.ts +29 -42
  85. package/src/create-client-log-callback.ts +101 -0
  86. package/src/create-proxy-provider.ts +89 -0
  87. package/src/index.ts +6 -7
  88. package/src/module.ts +88 -20
  89. package/src/static.ts +32 -3
  90. package/src/types.ts +15 -7
  91. package/src/util/compare-origin.ts +11 -0
  92. package/src/{v2/client/util/url.ts → util/normalize-uri.ts} +0 -10
  93. package/src/v2/IAuthClient.interface.ts +91 -0
  94. package/src/v2/IPublicClientApplication.interface.ts +71 -0
  95. package/src/v2/MsalProvider.interface.ts +92 -0
  96. package/src/v2/create-proxy-client.ts +186 -0
  97. package/src/v2/create-proxy-provider.ts +156 -0
  98. package/src/v2/map-account-info.ts +20 -0
  99. package/src/v2/map-authentication-result.ts +24 -0
  100. package/src/v2/types.ts +12 -0
  101. package/src/version.ts +1 -1
  102. package/src/versioning/resolve-version.ts +35 -28
  103. package/tsconfig.json +3 -0
  104. package/dist/esm/v2/client/behavior.js +0 -5
  105. package/dist/esm/v2/client/behavior.js.map +0 -1
  106. package/dist/esm/v2/client/client.js +0 -142
  107. package/dist/esm/v2/client/client.js.map +0 -1
  108. package/dist/esm/v2/client/create-auth-client.js +0 -36
  109. package/dist/esm/v2/client/create-auth-client.js.map +0 -1
  110. package/dist/esm/v2/client/index.js +0 -5
  111. package/dist/esm/v2/client/index.js.map +0 -1
  112. package/dist/esm/v2/client/log/console.js +0 -45
  113. package/dist/esm/v2/client/log/console.js.map +0 -1
  114. package/dist/esm/v2/client/request.js +0 -2
  115. package/dist/esm/v2/client/request.js.map +0 -1
  116. package/dist/esm/v2/client/util/browser.js.map +0 -1
  117. package/dist/esm/v2/client/util/url.js.map +0 -1
  118. package/dist/esm/v2/configurator.js +0 -42
  119. package/dist/esm/v2/configurator.js.map +0 -1
  120. package/dist/esm/v2/index.js +0 -3
  121. package/dist/esm/v2/index.js.map +0 -1
  122. package/dist/esm/v2/provider.js +0 -115
  123. package/dist/esm/v2/provider.js.map +0 -1
  124. package/dist/types/v2/client/behavior.d.ts +0 -13
  125. package/dist/types/v2/client/client.d.ts +0 -89
  126. package/dist/types/v2/client/create-auth-client.d.ts +0 -27
  127. package/dist/types/v2/client/index.d.ts +0 -5
  128. package/dist/types/v2/client/log/console.d.ts +0 -28
  129. package/dist/types/v2/client/request.d.ts +0 -65
  130. package/dist/types/v2/configurator.d.ts +0 -32
  131. package/dist/types/v2/index.d.ts +0 -2
  132. package/dist/types/v2/provider.d.ts +0 -59
  133. package/src/v2/client/behavior.ts +0 -14
  134. package/src/v2/client/client.ts +0 -180
  135. package/src/v2/client/create-auth-client.ts +0 -48
  136. package/src/v2/client/index.ts +0 -8
  137. package/src/v2/client/log/console.ts +0 -58
  138. package/src/v2/client/request.ts +0 -66
  139. package/src/v2/configurator.ts +0 -58
  140. package/src/v2/index.ts +0 -2
  141. package/src/v2/provider.ts +0 -178
  142. /package/dist/types/{v2/client/util/browser.d.ts → util/compare-origin.d.ts} +0 -0
  143. /package/dist/types/{v2/client/util/url.d.ts → util/normalize-uri.d.ts} +0 -0
  144. /package/src/{v2/client/util/browser.ts → util/redirect.ts} +0 -0
@@ -0,0 +1,91 @@
1
+ import type {
2
+ AuthenticationResult,
3
+ AccountInfo as AccountInfoBase,
4
+ IPublicClientApplication,
5
+ } from '@azure/msal-browser';
6
+
7
+ export type IdTokenClaims = {
8
+ aud: string;
9
+ exp: number;
10
+ };
11
+
12
+ export type AccountInfo = AccountInfoBase & {
13
+ idTokenClaims?: IdTokenClaims;
14
+ };
15
+
16
+ export type AuthBehavior = 'popup' | 'redirect';
17
+
18
+ export type AuthRequest = {
19
+ scopes?: string[];
20
+ loginHint?: string;
21
+ };
22
+
23
+ /**
24
+ * Interface for MSAL v2 compatible authentication client.
25
+ *
26
+ * This interface defines the contract for authentication clients that maintain
27
+ * backward compatibility with MSAL v2 API while using MSAL v4 implementation
28
+ * under the hood. This is useful for gradual migration scenarios.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * const client: IAuthClient_v2 = createProxyClient(baseClient);
33
+ *
34
+ * // Use v2 compatible API
35
+ * const account = client.account;
36
+ * const result = await client.login({ scopes: ['User.Read'] });
37
+ * ```
38
+ */
39
+ export interface IAuthClient extends IPublicClientApplication {
40
+ /**
41
+ * Tenant ID for the client domain
42
+ */
43
+ readonly tenantId: string;
44
+
45
+ /**
46
+ * Returns account for client tenant that MSAL currently has data for.
47
+ * (the account object is created at the time of successful login)
48
+ */
49
+ get account(): AccountInfo | undefined;
50
+
51
+ /**
52
+ * Check if the current account has valid claims
53
+ */
54
+ get hasValidClaims(): boolean;
55
+
56
+ /**
57
+ * Configured client ID
58
+ */
59
+ get clientId(): string | undefined;
60
+
61
+ /**
62
+ * Request origin from browser storage
63
+ */
64
+ get requestOrigin(): string | null;
65
+
66
+ /**
67
+ * Login user with optional silent authentication fallback
68
+ * @param options - Optional authentication request options
69
+ * @param behavior - Authentication method: 'popup' or 'redirect'
70
+ * @param silent - Whether to attempt silent authentication first
71
+ * @returns Promise resolving to authentication result or void
72
+ */
73
+ login(
74
+ options?: AuthRequest,
75
+ behavior?: AuthBehavior,
76
+ silent?: boolean,
77
+ ): Promise<AuthenticationResult | void>;
78
+
79
+ /**
80
+ * Acquire access token with optional silent authentication fallback
81
+ * @param options - Authentication request options
82
+ * @param behavior - Authentication method: 'popup' or 'redirect'
83
+ * @param silent - Whether to attempt silent authentication first
84
+ * @returns Promise resolving to authentication result or void
85
+ */
86
+ acquireToken(
87
+ options?: AuthRequest,
88
+ behavior?: AuthBehavior,
89
+ silent?: boolean,
90
+ ): Promise<AuthenticationResult | void>;
91
+ }
@@ -0,0 +1,71 @@
1
+ import type { AccountInfo, AuthenticationResult } from './types';
2
+
3
+ /**
4
+ * MSAL v2 compatible PublicClientApplication interface.
5
+ *
6
+ * This interface defines the contract for MSAL v2 PublicClientApplication
7
+ * to maintain backward compatibility while using MSAL v4 implementation.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const v4Client = new PublicClientApplication(config);
12
+ * const v2Client = createProxyClient_v2(v4Client);
13
+ *
14
+ * // Use v2-compatible methods
15
+ * const accounts = v2Client.getAllAccounts();
16
+ * const token = await v2Client.acquireTokenSilent({ scopes: ['User.Read'], account });
17
+ * ```
18
+ */
19
+ export interface IPublicClientApplication {
20
+ /**
21
+ * Get all cached accounts
22
+ * @returns Array of cached account information
23
+ */
24
+ getAllAccounts(): AccountInfo[];
25
+
26
+ /**
27
+ * Acquire token silently using cached credentials
28
+ * @param request - Token request parameters
29
+ * @returns Promise resolving to authentication result
30
+ */
31
+ acquireTokenSilent(request: {
32
+ scopes: string[];
33
+ account: AccountInfo;
34
+ }): Promise<AuthenticationResult>;
35
+
36
+ /**
37
+ * Login user via popup window
38
+ * @param request - Optional login request parameters
39
+ * @returns Promise resolving to authentication result
40
+ */
41
+ loginPopup(request?: { scopes?: string[] }): Promise<AuthenticationResult>;
42
+
43
+ /**
44
+ * Login user via redirect
45
+ * @param request - Optional login request parameters
46
+ * @returns Promise that resolves when redirect is initiated
47
+ */
48
+ loginRedirect(request?: { scopes?: string[] }): Promise<void>;
49
+
50
+ /**
51
+ * Logout user via redirect
52
+ * @param request - Optional logout request parameters
53
+ * @returns Promise that resolves when logout is complete
54
+ */
55
+ logoutRedirect(request?: {
56
+ postLogoutRedirectUri?: string;
57
+ account?: AccountInfo;
58
+ }): Promise<void>;
59
+
60
+ /**
61
+ * Handle authentication redirect after login/logout
62
+ * @returns Promise resolving to authentication result or null
63
+ */
64
+ handleRedirectPromise(): Promise<AuthenticationResult | null>;
65
+
66
+ /**
67
+ * Get the currently active account
68
+ * @returns Active account information or null
69
+ */
70
+ getActiveAccount(): AccountInfo | null;
71
+ }
@@ -0,0 +1,92 @@
1
+ import type { SemVer } from 'semver';
2
+ import type { MsalModuleVersion } from '../static';
3
+ import type { IPublicClientApplication } from './IPublicClientApplication.interface';
4
+ import type { AccountInfo, AuthenticationResult } from './types';
5
+
6
+ /**
7
+ * Interface for MSAL v2 compatible authentication provider.
8
+ *
9
+ * This interface defines the contract for authentication providers that maintain
10
+ * backward compatibility with MSAL v2 API while using MSAL v4 implementation
11
+ * under the hood. This is useful for gradual migration scenarios.
12
+ */
13
+ export interface IMsalProvider {
14
+ /** Current version of the provider (MSAL module version) */
15
+ version: string | SemVer;
16
+
17
+ /** Current MSAL module version */
18
+ msalVersion: MsalModuleVersion;
19
+
20
+ /**
21
+ * The MSAL PublicClientApplication instance (v2 compatible)
22
+ */
23
+ readonly client: IPublicClientApplication;
24
+
25
+ /**
26
+ * The current authenticated account (v2 compatibility)
27
+ * @deprecated Use activeAccount instead
28
+ */
29
+ readonly defaultAccount: AccountInfo | undefined;
30
+
31
+ /**
32
+ * The client configuration used to initialize this provider
33
+ * @deprecated Configuration should not be exposed
34
+ */
35
+ readonly defaultConfig: unknown | undefined;
36
+
37
+ /**
38
+ * The MSAL client instance (v2 compatibility)
39
+ * @deprecated Use client instead
40
+ */
41
+ readonly defaultClient: IPublicClientApplication;
42
+
43
+ /**
44
+ * Create a new MSAL client instance
45
+ * @deprecated This method is deprecated in MSAL v4
46
+ */
47
+ createClient(): IPublicClientApplication;
48
+
49
+ /**
50
+ * Acquire an access token for the specified scopes
51
+ * @param req - Auth request options (v2 compatible)
52
+ */
53
+ acquireAccessToken(req: { scopes: string[]; account?: AccountInfo }): Promise<string | undefined>;
54
+
55
+ /**
56
+ * Acquire full authentication result
57
+ * @param req - Auth request options (v2 compatible)
58
+ */
59
+ acquireToken(req: {
60
+ scopes: string[];
61
+ account?: AccountInfo;
62
+ }): Promise<AuthenticationResult | undefined>;
63
+
64
+ /**
65
+ * Login user interactively
66
+ * @param options - Login options (v2 compatible)
67
+ */
68
+ login(options?: { onlyIfRequired?: boolean }): Promise<void>;
69
+
70
+ /**
71
+ * Logout user
72
+ * @param options - Logout options (v2 compatible)
73
+ */
74
+ logout(options?: { redirectUri?: string }): Promise<void>;
75
+
76
+ /**
77
+ * Handle authentication redirect
78
+ */
79
+ handleRedirect(): Promise<void | null>;
80
+
81
+ /**
82
+ * Create a proxy provider for version compatibility
83
+ * @param version - Version string
84
+ * @returns Proxy provider
85
+ */
86
+ createProxyProvider<T = IMsalProvider>(version: string): T;
87
+
88
+ /**
89
+ * Dispose of the provider and clean up resources
90
+ */
91
+ dispose(): void;
92
+ }
@@ -0,0 +1,186 @@
1
+ import type { IMsalClient } from '../MsalClient.interface';
2
+ import type { IAuthClient } from './IAuthClient.interface';
3
+ import { mapAccountInfo } from './map-account-info';
4
+ import { mapAuthenticationResult } from './map-authentication-result';
5
+ import type { AccountInfo } from './types';
6
+
7
+ /**
8
+ * Creates a v2-compatible proxy for MSAL PublicClientApplication.
9
+ *
10
+ * This function creates a proxy that wraps the MSAL v4 PublicClientApplication
11
+ * and provides v2-compatible method signatures and return types.
12
+ *
13
+ * @param client - The MSAL v4 PublicClientApplication instance
14
+ * @returns A proxy client with v2-compatible interface
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const v4Client = new PublicClientApplication(config);
19
+ * const v2Client = createProxyClient_v2(v4Client);
20
+ *
21
+ * // Use v2-compatible methods
22
+ * const accounts = v2Client.getAllAccounts();
23
+ * const token = await v2Client.acquireTokenSilent({ scopes: ['User.Read'], account });
24
+ * ```
25
+ */
26
+ export function createProxyClient(client: IMsalClient): IAuthClient {
27
+ const proxy = new Proxy(client, {
28
+ get: (target: IMsalClient, prop: keyof IAuthClient) => {
29
+ switch (prop) {
30
+ case 'getAllAccounts': {
31
+ return () => {
32
+ return target.getAllAccounts().map(mapAccountInfo);
33
+ };
34
+ }
35
+
36
+ case 'acquireTokenSilent': {
37
+ return async (request: { scopes: string[]; account: AccountInfo }) => {
38
+ const result = await target.acquireTokenSilent({
39
+ scopes: request.scopes,
40
+ account: request.account, // AccountInfo is compatible between v2/v4
41
+ });
42
+
43
+ return mapAuthenticationResult(result);
44
+ };
45
+ }
46
+
47
+ case 'loginPopup': {
48
+ return async (request?: { scopes?: string[] }) => {
49
+ const result = await target.loginPopup({
50
+ scopes: request?.scopes || [],
51
+ });
52
+
53
+ return mapAuthenticationResult(result);
54
+ };
55
+ }
56
+
57
+ case 'logoutRedirect': {
58
+ return async (request?: { postLogoutRedirectUri?: string; account?: AccountInfo }) => {
59
+ await target.logoutRedirect({
60
+ postLogoutRedirectUri: request?.postLogoutRedirectUri,
61
+ account: request?.account,
62
+ });
63
+ };
64
+ }
65
+
66
+ case 'handleRedirectPromise': {
67
+ return async () => {
68
+ const result = await target.handleRedirectPromise();
69
+
70
+ if (!result) {
71
+ return null;
72
+ }
73
+
74
+ return mapAuthenticationResult(result);
75
+ };
76
+ }
77
+
78
+ case 'getActiveAccount': {
79
+ return () => {
80
+ const account = target.getActiveAccount();
81
+ if (!account) {
82
+ return null;
83
+ }
84
+
85
+ return mapAccountInfo(account);
86
+ };
87
+ }
88
+
89
+ case 'tenantId': {
90
+ return target.tenantId;
91
+ }
92
+
93
+ case 'account': {
94
+ const account = target.getActiveAccount();
95
+ return account ? mapAccountInfo(account) : undefined;
96
+ }
97
+
98
+ case 'hasValidClaims': {
99
+ return target.hasValidClaims;
100
+ }
101
+
102
+ case 'clientId': {
103
+ return target.getConfiguration().auth.clientId;
104
+ }
105
+
106
+ case 'requestOrigin': {
107
+ return target.getConfiguration().auth.redirectUri;
108
+ }
109
+
110
+ case 'login': {
111
+ return async (
112
+ options?: { scopes?: string[]; loginHint?: string },
113
+ behavior?: 'popup' | 'redirect',
114
+ silent?: boolean,
115
+ ) => {
116
+ return await target.login({
117
+ request: {
118
+ scopes: options?.scopes || [],
119
+ loginHint: options?.loginHint,
120
+ },
121
+ behavior: behavior,
122
+ silent: silent,
123
+ });
124
+ };
125
+ }
126
+
127
+ case 'acquireToken': {
128
+ return async (
129
+ options?: { scopes?: string[]; loginHint?: string },
130
+ behavior?: 'popup' | 'redirect',
131
+ silent?: boolean,
132
+ ) => {
133
+ return await target.acquireToken({
134
+ request: {
135
+ scopes: options?.scopes || [],
136
+ account: target.getActiveAccount() ?? undefined,
137
+ loginHint: options?.loginHint,
138
+ },
139
+ behavior: behavior,
140
+ silent: silent,
141
+ });
142
+ };
143
+ }
144
+
145
+ case 'initialize':
146
+ case 'acquireTokenPopup':
147
+ case 'acquireTokenRedirect':
148
+ case 'acquireTokenByCode':
149
+ case 'addEventCallback':
150
+ case 'removeEventCallback':
151
+ case 'addPerformanceCallback':
152
+ case 'removePerformanceCallback':
153
+ case 'enableAccountStorageEvents':
154
+ case 'disableAccountStorageEvents':
155
+ case 'getConfiguration':
156
+ case 'setActiveAccount':
157
+ case 'getAccountByHomeId':
158
+ case 'getAccountByLocalId':
159
+ case 'getAccountByUsername':
160
+ case 'loginRedirect':
161
+ case 'logout':
162
+ case 'logoutPopup':
163
+ case 'ssoSilent':
164
+ case 'getTokenCache':
165
+ case 'setLogger':
166
+ case 'getLogger':
167
+ case 'initializeWrapperLibrary':
168
+ case 'setNavigationClient':
169
+ case 'hydrateCache':
170
+ case 'getAccount':
171
+ case 'clearCache': {
172
+ return target[prop];
173
+ }
174
+
175
+ default: {
176
+ // TypeScript-only guard to catch missing properties at compile time
177
+ const _exhaustiveCheck: never = prop;
178
+ // For any other properties, return the original value
179
+ return (target as unknown as IAuthClient)[_exhaustiveCheck];
180
+ }
181
+ }
182
+ },
183
+ });
184
+
185
+ return proxy as unknown as IAuthClient;
186
+ }
@@ -0,0 +1,156 @@
1
+ import type { IMsalProvider } from '../MsalProvider.interface';
2
+ import type { IMsalProvider as IMsalProvider_v2 } from './MsalProvider.interface';
3
+ import type { AccountInfo as AccountInfo_v2 } from './types';
4
+ import { createProxyClient } from './create-proxy-client';
5
+ import { mapAccountInfo } from './map-account-info';
6
+ import { MsalModuleVersion } from '../static';
7
+
8
+ /**
9
+ * Creates a proxy provider for MSAL v2 compatibility.
10
+ *
11
+ * This function creates a Proxy that wraps the MSAL v4 provider and provides
12
+ * v2-compatible method signatures and return types while using the latest
13
+ * MSAL v4 implementation under the hood. The proxy handles type conversions
14
+ * and method adaptations to maintain backward compatibility.
15
+ *
16
+ * @param provider - The base MSAL v4 provider instance to wrap
17
+ * @returns A proxy provider implementing the v2-compatible interface
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const baseProvider = new MsalProvider(config);
22
+ * const v2Proxy = createProxyProvider(baseProvider);
23
+ *
24
+ * // Use v2-compatible API
25
+ * await v2Proxy.login();
26
+ * const token = await v2Proxy.acquireAccessToken({ scopes: ['User.Read'] });
27
+ * ```
28
+ */
29
+ export function createProxyProvider(provider: IMsalProvider): IMsalProvider_v2 {
30
+ // Create a v2-compatible client wrapper using the new client proxy
31
+ const v2Client = createProxyClient(provider.client);
32
+
33
+ // Use Proxy to intercept property access and provide v2-compatible implementations
34
+ const proxy = new Proxy(provider, {
35
+ get: (target: IMsalProvider, prop: keyof IMsalProvider_v2) => {
36
+ switch (prop) {
37
+ case 'version': {
38
+ return provider.version;
39
+ }
40
+ case 'msalVersion': {
41
+ return MsalModuleVersion.V2;
42
+ }
43
+ case 'client': {
44
+ // Return the v2-compatible client wrapper
45
+ return v2Client as unknown as IMsalProvider_v2['client'];
46
+ }
47
+ case 'defaultClient': {
48
+ // Deprecated property - redirect to client with warning
49
+ console.warn('defaultClient is deprecated, use client instead');
50
+ return v2Client as unknown as IMsalProvider_v2['defaultClient'];
51
+ }
52
+ case 'defaultAccount': {
53
+ // Map v4 account to v2 format for backward compatibility
54
+ const account = target.account;
55
+ const defaultAccount: IMsalProvider_v2['defaultAccount'] = account
56
+ ? mapAccountInfo(account)
57
+ : undefined;
58
+ return defaultAccount;
59
+ }
60
+ case 'defaultConfig': {
61
+ // Deprecated property - not available in v4
62
+ console.warn('defaultConfig is deprecated and not available in v4');
63
+ return undefined;
64
+ }
65
+ case 'createClient': {
66
+ // Deprecated method - return function that returns v2 client
67
+ console.warn('createClient is deprecated in MSAL v4');
68
+ const createClient: IMsalProvider_v2['createClient'] = () => v2Client;
69
+ return createClient;
70
+ }
71
+ case 'acquireToken': {
72
+ // Adapt v4 acquireToken to v2 signature with proper type mapping
73
+ const acquireToken: IMsalProvider_v2['acquireToken'] = async (req: {
74
+ scopes: string[];
75
+ account?: AccountInfo_v2;
76
+ }) => {
77
+ const result = await target.acquireToken({
78
+ request: { scopes: req.scopes, account: req.account },
79
+ });
80
+
81
+ // Convert null to undefined for v2 compatibility
82
+ return result || undefined;
83
+ };
84
+ return acquireToken;
85
+ }
86
+ case 'acquireAccessToken': {
87
+ // Adapt v4 acquireAccessToken to v2 signature
88
+ const acquireAccessToken: IMsalProvider_v2['acquireAccessToken'] = async (req: {
89
+ scopes: string[];
90
+ account?: AccountInfo_v2;
91
+ }) => {
92
+ return await target.acquireAccessToken({
93
+ request: { scopes: req.scopes, account: req.account },
94
+ });
95
+ };
96
+ return acquireAccessToken;
97
+ }
98
+ case 'login': {
99
+ // Adapt v4 login to v2 signature with optional parameters
100
+ const login: IMsalProvider_v2['login'] = async (options?: {
101
+ onlyIfRequired?: boolean;
102
+ }) => {
103
+ // Skip login if already authenticated and onlyIfRequired is true
104
+ if (options?.onlyIfRequired && target.account) {
105
+ return;
106
+ }
107
+ // Call v4 login with empty scopes (v2 behavior)
108
+ await target.login({ request: { scopes: [] } });
109
+ };
110
+ return login;
111
+ }
112
+ case 'logout': {
113
+ // Adapt v4 logout to v2 signature
114
+ const logout: IMsalProvider_v2['logout'] = async (options?: { redirectUri?: string }) => {
115
+ await target.logout({ redirectUri: options?.redirectUri });
116
+ };
117
+ return logout;
118
+ }
119
+ case 'handleRedirect': {
120
+ // Adapt v4 handleRedirect to v2 signature
121
+ const handleRedirect: IMsalProvider_v2['handleRedirect'] = async () => {
122
+ await target.handleRedirect();
123
+ // v2 expects null after redirect handling
124
+ return null;
125
+ };
126
+ return handleRedirect;
127
+ }
128
+ case 'createProxyProvider': {
129
+ // Generic method to create proxy providers for different versions
130
+ const createProxyProvider: IMsalProvider_v2['createProxyProvider'] = <T = IMsalProvider>(
131
+ version: string,
132
+ ) => target.createProxyProvider(version as MsalModuleVersion) as T;
133
+ return createProxyProvider;
134
+ }
135
+ case 'dispose': {
136
+ // No-op dispose method for v2 compatibility
137
+ return () => {
138
+ /** noop */
139
+ };
140
+ }
141
+ default: {
142
+ if (prop === 'then') {
143
+ return undefined;
144
+ }
145
+ // Exhaustive check to ensure all v2 properties are handled
146
+ const exhaustiveCheck: never = prop;
147
+ // Fallback: return original property from target for any unhandled cases
148
+ return (target as IMsalProvider)[exhaustiveCheck];
149
+ }
150
+ }
151
+ },
152
+ });
153
+
154
+ // Return the proxy cast to v2 interface for type safety
155
+ return proxy as unknown as IMsalProvider_v2;
156
+ }
@@ -0,0 +1,20 @@
1
+ import type { AccountInfo } from '@azure/msal-browser';
2
+ import type { AccountInfo as AccountInfo_v2 } from './types';
3
+
4
+ /**
5
+ * Maps current AccountInfo to v2 AccountInfo format.
6
+ *
7
+ * @param account - The current AccountInfo to convert
8
+ * @returns The v2 AccountInfo format
9
+ */
10
+ export function mapAccountInfo(account: AccountInfo): AccountInfo_v2 {
11
+ return {
12
+ homeAccountId: account.homeAccountId,
13
+ environment: account.environment,
14
+ tenantId: account.tenantId,
15
+ username: account.username,
16
+ localAccountId: account.localAccountId,
17
+ name: account.name,
18
+ idTokenClaims: account.idTokenClaims,
19
+ };
20
+ }
@@ -0,0 +1,24 @@
1
+ import type { AuthenticationResult } from '@azure/msal-browser';
2
+ import type { AuthenticationResult as AuthenticationResult_v2 } from './types';
3
+ import { mapAccountInfo } from './map-account-info';
4
+
5
+ /**
6
+ * Maps current AuthenticationResult to v2 AuthenticationResult format.
7
+ *
8
+ * @param result - The current AuthenticationResult to convert
9
+ * @returns The v2 AuthenticationResult format
10
+ */
11
+ export function mapAuthenticationResult(result: AuthenticationResult): AuthenticationResult_v2 {
12
+ return {
13
+ authority: result.authority,
14
+ uniqueId: result.uniqueId,
15
+ tenantId: result.tenantId,
16
+ scopes: result.scopes,
17
+ account: result.account ? mapAccountInfo(result.account) : null,
18
+ idToken: result.idToken,
19
+ idTokenClaims: result.idTokenClaims,
20
+ accessToken: result.accessToken,
21
+ expiresOn: result.expiresOn,
22
+ tokenType: result.tokenType,
23
+ };
24
+ }
package/src/v2/types.ts CHANGED
@@ -1,3 +1,9 @@
1
+ /**
2
+ * MSAL v2 compatible AccountInfo type.
3
+ *
4
+ * This type represents account information in MSAL v2 format
5
+ * to maintain backward compatibility while using MSAL v4 implementation.
6
+ */
1
7
  export type AccountInfo = {
2
8
  homeAccountId: string;
3
9
  environment: string;
@@ -10,6 +16,12 @@ export type AccountInfo = {
10
16
  };
11
17
  };
12
18
 
19
+ /**
20
+ * MSAL v2 compatible AuthenticationResult type.
21
+ *
22
+ * This type represents authentication results in MSAL v2 format
23
+ * to maintain backward compatibility while using MSAL v4 implementation.
24
+ */
13
25
  export type AuthenticationResult = {
14
26
  authority: string;
15
27
  uniqueId: string;
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '5.1.1';
2
+ export const version = '6.0.0-next.0';