@microsoft/agents-hosting 1.6.0-beta.8.g226709c215 → 1.6.1

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 (94) hide show
  1. package/dist/package.json +4 -9
  2. package/dist/src/agent-client/agentClient.js +2 -2
  3. package/dist/src/agent-client/agentClient.js.map +1 -1
  4. package/dist/src/agent-client/agentResponseHandler.js +2 -2
  5. package/dist/src/agent-client/agentResponseHandler.js.map +1 -1
  6. package/dist/src/app/agentApplication.js +28 -2
  7. package/dist/src/app/agentApplication.js.map +1 -1
  8. package/dist/src/app/agentApplicationOptions.d.ts +10 -0
  9. package/dist/src/app/attachmentDownloader.js +5 -10
  10. package/dist/src/app/attachmentDownloader.js.map +1 -1
  11. package/dist/src/app/auth/authorizationManager.d.ts +4 -0
  12. package/dist/src/app/auth/authorizationManager.js +94 -67
  13. package/dist/src/app/auth/authorizationManager.js.map +1 -1
  14. package/dist/src/app/auth/handlers/azureBotAuthorization.js +2 -2
  15. package/dist/src/app/auth/handlers/azureBotAuthorization.js.map +1 -1
  16. package/dist/src/app/proactive/createConversationOptionsBuilder.js +10 -6
  17. package/dist/src/app/proactive/createConversationOptionsBuilder.js.map +1 -1
  18. package/dist/src/app/proactive/proactive.d.ts +1 -0
  19. package/dist/src/app/proactive/proactive.js +30 -15
  20. package/dist/src/app/proactive/proactive.js.map +1 -1
  21. package/dist/src/app/teamsAttachmentDownloader.js +6 -8
  22. package/dist/src/app/teamsAttachmentDownloader.js.map +1 -1
  23. package/dist/src/auth/authConfiguration.d.ts +2 -143
  24. package/dist/src/auth/authConfiguration.js +301 -257
  25. package/dist/src/auth/authConfiguration.js.map +1 -1
  26. package/dist/src/auth/jwt-middleware.js +2 -1
  27. package/dist/src/auth/jwt-middleware.js.map +1 -1
  28. package/dist/src/auth/msalConnectionManager.js +27 -14
  29. package/dist/src/auth/msalConnectionManager.js.map +1 -1
  30. package/dist/src/auth/msalTokenProvider.d.ts +7 -0
  31. package/dist/src/auth/msalTokenProvider.js +188 -44
  32. package/dist/src/auth/msalTokenProvider.js.map +1 -1
  33. package/dist/src/auth/settings.d.ts +327 -0
  34. package/dist/src/auth/settings.js +158 -0
  35. package/dist/src/auth/settings.js.map +1 -0
  36. package/dist/src/cloudAdapter.d.ts +58 -1
  37. package/dist/src/cloudAdapter.js +232 -52
  38. package/dist/src/cloudAdapter.js.map +1 -1
  39. package/dist/src/connector-client/connectorClient.d.ts +12 -8
  40. package/dist/src/connector-client/connectorClient.js +99 -82
  41. package/dist/src/connector-client/connectorClient.js.map +1 -1
  42. package/dist/src/errorHelper.js +85 -7
  43. package/dist/src/errorHelper.js.map +1 -1
  44. package/dist/src/getProductInfo.d.ts +23 -0
  45. package/dist/src/getProductInfo.js +71 -1
  46. package/dist/src/getProductInfo.js.map +1 -1
  47. package/dist/src/headerPropagation.d.ts +17 -2
  48. package/dist/src/headerPropagation.js +46 -24
  49. package/dist/src/headerPropagation.js.map +1 -1
  50. package/dist/src/httpClient.d.ts +60 -0
  51. package/dist/src/httpClient.js +173 -0
  52. package/dist/src/httpClient.js.map +1 -0
  53. package/dist/src/index.d.ts +2 -1
  54. package/dist/src/index.js +7 -2
  55. package/dist/src/index.js.map +1 -1
  56. package/dist/src/oauth/userTokenClient.d.ts +5 -4
  57. package/dist/src/oauth/userTokenClient.js +97 -78
  58. package/dist/src/oauth/userTokenClient.js.map +1 -1
  59. package/dist/src/observability/traces.d.ts +11 -4
  60. package/dist/src/observability/traces.js +39 -7
  61. package/dist/src/observability/traces.js.map +1 -1
  62. package/dist/src/utils/env.d.ts +50 -0
  63. package/dist/src/utils/env.js +113 -0
  64. package/dist/src/utils/env.js.map +1 -0
  65. package/dist/src/utils.d.ts +10 -0
  66. package/dist/src/utils.js +18 -0
  67. package/dist/src/utils.js.map +1 -0
  68. package/package.json +4 -9
  69. package/src/agent-client/agentClient.ts +2 -2
  70. package/src/agent-client/agentResponseHandler.ts +2 -2
  71. package/src/app/agentApplication.ts +30 -3
  72. package/src/app/agentApplicationOptions.ts +11 -0
  73. package/src/app/attachmentDownloader.ts +6 -8
  74. package/src/app/auth/authorizationManager.ts +84 -41
  75. package/src/app/auth/handlers/azureBotAuthorization.ts +2 -2
  76. package/src/app/proactive/createConversationOptionsBuilder.ts +8 -4
  77. package/src/app/proactive/proactive.ts +39 -23
  78. package/src/app/teamsAttachmentDownloader.ts +7 -6
  79. package/src/auth/authConfiguration.ts +317 -356
  80. package/src/auth/jwt-middleware.ts +1 -1
  81. package/src/auth/msalConnectionManager.ts +27 -10
  82. package/src/auth/msalTokenProvider.ts +180 -42
  83. package/src/auth/settings.ts +323 -0
  84. package/src/cloudAdapter.ts +291 -12
  85. package/src/connector-client/connectorClient.ts +116 -94
  86. package/src/errorHelper.ts +96 -7
  87. package/src/getProductInfo.ts +79 -1
  88. package/src/headerPropagation.ts +55 -23
  89. package/src/httpClient.ts +223 -0
  90. package/src/index.ts +5 -1
  91. package/src/oauth/userTokenClient.ts +103 -84
  92. package/src/observability/traces.ts +39 -8
  93. package/src/utils/env.ts +105 -0
  94. package/src/utils.ts +14 -0
@@ -21,7 +21,7 @@ const logger = debug('agents:jwt-middleware')
21
21
  export function buildJwksUri (iss: string, authConfig: AuthConfiguration): string {
22
22
  return iss === 'https://api.botframework.com'
23
23
  ? 'https://login.botframework.com/v1/.well-known/keys'
24
- : `${resolveAuthority(authConfig.authority, authConfig.tenantId)}/discovery/v2.0/keys`
24
+ : `${resolveAuthority(authConfig.authorityEndpoint ?? authConfig.authority, authConfig.tenantId)}/discovery/v2.0/keys`
25
25
  }
26
26
 
27
27
  /**
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { Activity, RoleTypes } from '@microsoft/agents-activity'
7
7
  import { debug } from '@microsoft/agents-telemetry'
8
- import { AuthConfiguration, resolveAuthority } from './authConfiguration'
8
+ import { AuthConfiguration, AuthType, resolveAuthority } from './authConfiguration'
9
9
  import { Connections } from './connections'
10
10
  import { MsalTokenProvider } from './msalTokenProvider'
11
11
  import { JwtPayload } from 'jsonwebtoken'
@@ -44,13 +44,16 @@ export class MsalConnectionManager implements Connections {
44
44
 
45
45
  for (const [name, provider] of this._connections.entries()) {
46
46
  const cfg = provider.connectionSettings
47
- const authType = cfg?.certPemFile
48
- ? 'certificate'
49
- : cfg?.clientSecret
50
- ? 'clientSecret'
51
- : cfg?.WIDAssertionFile || cfg?.FICClientId
52
- ? 'workloadIdentity'
53
- : 'none'
47
+ const authType = cfg?.authType ??
48
+ (cfg?.certPemFile
49
+ ? AuthType.Certificate
50
+ : cfg?.clientSecret
51
+ ? AuthType.ClientSecret
52
+ : cfg?.WIDAssertionFile
53
+ ? AuthType.WorkloadIdentity
54
+ : cfg?.federatedClientId || cfg?.FICClientId
55
+ ? AuthType.FederatedCredentials
56
+ : 'none')
54
57
  logger.debug('connection "%s" clientId=%s tenantId=%s authType=%s', name, cfg?.clientId ?? '<none>', cfg?.tenantId ?? '<none>', authType)
55
58
  }
56
59
 
@@ -185,13 +188,27 @@ export class MsalConnectionManager implements Connections {
185
188
 
186
189
  private applyConnectionDefaults (conn: MsalTokenProvider): MsalTokenProvider {
187
190
  if (conn.connectionSettings) {
188
- conn.connectionSettings.authority ??= 'https://login.microsoftonline.com'
191
+ conn.connectionSettings.authorityEndpoint ??= conn.connectionSettings.authority || 'https://login.microsoftonline.com'
192
+ conn.connectionSettings.authority ??= conn.connectionSettings.authorityEndpoint
189
193
  conn.connectionSettings.issuers ??= [
190
194
  'https://api.botframework.com',
191
195
  `${resolveAuthority('https://sts.windows.net', conn.connectionSettings.tenantId)}/`,
192
- `${resolveAuthority(conn.connectionSettings.authority, conn.connectionSettings.tenantId)}/v2.0`
196
+ `${resolveAuthority(conn.connectionSettings.authorityEndpoint, conn.connectionSettings.tenantId)}/v2.0`
193
197
  ]
198
+ // For backward compatibility
199
+ if (conn.connectionSettings.federatedClientId) {
200
+ conn.connectionSettings.FICClientId = conn.connectionSettings.federatedClientId
201
+ }
202
+
203
+ if (conn.connectionSettings.scopes?.length) {
204
+ conn.connectionSettings.scope = conn.connectionSettings.scopes?.[0]
205
+ }
206
+
207
+ if (conn.connectionSettings.authorityEndpoint) {
208
+ conn.connectionSettings.authority = conn.connectionSettings.authorityEndpoint
209
+ }
194
210
  }
211
+
195
212
  return conn
196
213
  }
197
214
  }
@@ -4,20 +4,30 @@
4
4
  */
5
5
 
6
6
  import { ConfidentialClientApplication, LogLevel, ManagedIdentityApplication, NodeSystemOptions } from '@azure/msal-node'
7
- import axios from 'axios'
8
- import { AuthConfiguration, resolveAuthority as resolveAuthorityUtil } from './authConfiguration'
7
+ import { AuthConfiguration, AuthType, resolveAuthority as resolveAuthorityUtil } from './authConfiguration'
9
8
  import { AuthProvider } from './authProvider'
10
9
  import { debug, trace } from '@microsoft/agents-telemetry'
11
- import { v4 } from 'uuid'
10
+ import { randomUUID } from 'crypto'
12
11
  import { MemoryCache } from './MemoryCache'
13
12
  import jwt from 'jsonwebtoken'
14
13
 
15
14
  import fs from 'fs'
16
15
  import crypto from 'crypto'
17
16
  import { AuthenticationTraceDefinitions } from '../observability'
17
+ import { ExceptionHelper } from '@microsoft/agents-activity'
18
+ import { Errors } from '../errorHelper'
18
19
 
19
20
  const audience = 'api://AzureADTokenExchange'
20
21
  const logger = debug('agents:msal')
22
+ const agenticTokenRequestTimeoutMs = 30000
23
+
24
+ function isAbortError (error: unknown): error is Error {
25
+ return error instanceof Error && error.name === 'AbortError'
26
+ }
27
+
28
+ function createTokenRequestTimeoutError (timeoutMs: number): Error {
29
+ return ExceptionHelper.generateException(Error, Errors.TokenRequestTimeout, undefined, { timeoutMs: timeoutMs.toString() })
30
+ }
21
31
 
22
32
  /**
23
33
  * Provides tokens using MSAL.
@@ -70,34 +80,77 @@ export class MsalTokenProvider implements AuthProvider {
70
80
  }
71
81
 
72
82
  let token
73
- if (authConfig.WIDAssertionFile !== undefined) {
74
- record({ method: 'wid' })
75
- logger.debug('getAccessToken via WID clientId=%s scope=%s', authConfig.clientId, actualScope)
83
+ if (authConfig.authType) {
84
+ record({ method: authConfig.authType })
85
+ logger.debug(`getAccessToken via ${authConfig.authType} clientId=${authConfig.clientId} scope=${actualScope}`)
86
+ switch (authConfig.authType) {
87
+ case AuthType.WorkloadIdentity: {
88
+ const tokenFilePath = authConfig.federatedTokenFile ?? authConfig.WIDAssertionFile
89
+ if (!tokenFilePath) {
90
+ throw ExceptionHelper.generateException(Error, Errors.WorkloadIdentityTokenFileRequired)
91
+ }
92
+ token = await this.acquireAccessTokenViaWID(authConfig, actualScope)
93
+ break
94
+ }
95
+ case AuthType.FederatedCredentials:
96
+ if (!authConfig.federatedClientId && !authConfig.FICClientId) {
97
+ throw ExceptionHelper.generateException(Error, Errors.FICClientIdRequired)
98
+ }
99
+ token = await this.acquireAccessTokenViaFIC(authConfig, actualScope)
100
+ break
101
+ case AuthType.ClientSecret:
102
+ if (!authConfig.clientSecret) {
103
+ throw ExceptionHelper.generateException(Error, Errors.ClientSecretRequired)
104
+ }
105
+ token = await this.acquireAccessTokenViaSecret(authConfig, actualScope)
106
+ break
107
+ case AuthType.Certificate:
108
+ case AuthType.CertificateSubjectName:
109
+ if (!authConfig.certPemFile || !authConfig.certKeyFile) {
110
+ throw ExceptionHelper.generateException(Error, Errors.CertificateFilesRequired)
111
+ }
112
+ token = await this.acquireTokenWithCertificate(authConfig, actualScope)
113
+ break
114
+ case AuthType.UserManagedIdentity:
115
+ if (!authConfig.clientId) {
116
+ throw ExceptionHelper.generateException(Error, Errors.ClientIdRequiredForUserManagedIdentity)
117
+ }
118
+ token = await this.acquireTokenWithUserAssignedIdentity(authConfig, actualScope)
119
+ break
120
+ case AuthType.SystemManagedIdentity:
121
+ token = await this.acquireTokenWithSystemAssignedIdentity(authConfig, actualScope)
122
+ break
123
+ default:
124
+ throw ExceptionHelper.generateException(Error, Errors.UnsupportedAuthType, undefined, { authType: authConfig.authType })
125
+ }
126
+ } else if (authConfig.WIDAssertionFile !== undefined) {
127
+ record({ method: AuthType.WorkloadIdentity })
128
+ logger.debug('getAccessToken via method=%s clientId=%s scope=%s', AuthType.WorkloadIdentity, authConfig.clientId, actualScope)
76
129
  token = await this.acquireAccessTokenViaWID(authConfig, actualScope)
77
- } else if (authConfig.FICClientId !== undefined) {
78
- record({ method: 'fic' })
79
- logger.debug('getAccessToken via FIC clientId=%s scope=%s', authConfig.clientId, actualScope)
130
+ } else if (authConfig.federatedClientId !== undefined || authConfig.FICClientId !== undefined) {
131
+ record({ method: AuthType.FederatedCredentials })
132
+ logger.debug('getAccessToken via method=%s clientId=%s scope=%s', AuthType.FederatedCredentials, authConfig.clientId, actualScope)
80
133
  token = await this.acquireAccessTokenViaFIC(authConfig, actualScope)
81
134
  } else if (authConfig.clientSecret !== undefined) {
82
- record({ method: 'secret' })
83
- logger.debug('getAccessToken via secret clientId=%s scope=%s', authConfig.clientId, actualScope)
135
+ record({ method: AuthType.ClientSecret })
136
+ logger.debug('getAccessToken via method=%s clientId=%s scope=%s', AuthType.ClientSecret, authConfig.clientId, actualScope)
84
137
  token = await this.acquireAccessTokenViaSecret(authConfig, actualScope)
85
138
  } else if (authConfig.certPemFile !== undefined &&
86
139
  authConfig.certKeyFile !== undefined) {
87
- record({ method: 'certificate' })
88
- logger.debug('getAccessToken via certificate clientId=%s scope=%s', authConfig.clientId, actualScope)
140
+ record({ method: AuthType.Certificate })
141
+ logger.debug('getAccessToken via method=%s clientId=%s scope=%s', AuthType.Certificate, authConfig.clientId, actualScope)
89
142
  token = await this.acquireTokenWithCertificate(authConfig, actualScope)
90
143
  } else if (authConfig.clientSecret === undefined &&
91
144
  authConfig.certPemFile === undefined &&
92
145
  authConfig.certKeyFile === undefined) {
93
- record({ method: 'managed_identity' })
94
- logger.debug('getAccessToken via managed identity clientId=%s scope=%s', authConfig.clientId, actualScope)
146
+ record({ method: AuthType.UserManagedIdentity })
147
+ logger.debug('getAccessToken via method=%s clientId=%s scope=%s', AuthType.UserManagedIdentity, authConfig.clientId, actualScope)
95
148
  token = await this.acquireTokenWithUserAssignedIdentity(authConfig, actualScope)
96
149
  } else {
97
- throw new Error('Invalid authConfig. ')
150
+ throw ExceptionHelper.generateException(Error, Errors.InvalidAuthConfig)
98
151
  }
99
152
  if (token === undefined) {
100
- throw new Error('Failed to acquire token')
153
+ throw ExceptionHelper.generateException(Error, Errors.FailedToAcquireToken)
101
154
  }
102
155
 
103
156
  return token
@@ -137,7 +190,7 @@ export class MsalTokenProvider implements AuthProvider {
137
190
  const cca = new ConfidentialClientApplication({
138
191
  auth: {
139
192
  clientId: authConfig.clientId as string,
140
- authority: `${authConfig.authority}/${authConfig.tenantId || 'botframework.com'}`,
193
+ authority: `${authConfig.authorityEndpoint ?? authConfig.authority}/${authConfig.tenantId || 'botframework.com'}`,
141
194
  clientSecret: authConfig.clientSecret
142
195
  },
143
196
  system: this.sysOptions
@@ -174,7 +227,7 @@ export class MsalTokenProvider implements AuthProvider {
174
227
 
175
228
  const token = await cca.acquireTokenByClientCredential({
176
229
  scopes: ['api://AzureAdTokenExchange/.default'],
177
- correlationId: v4(),
230
+ correlationId: randomUUID(),
178
231
  azureRegion: this.connectionSettings?.azureRegion
179
232
  })
180
233
 
@@ -193,16 +246,16 @@ export class MsalTokenProvider implements AuthProvider {
193
246
  * @returns
194
247
  */
195
248
  private resolveAuthority (tenantId?: string) : string {
196
- const { authority: configuredAuth, tenantId: configuredTenantId } = this.connectionSettings ?? {}
249
+ const { authorityEndpoint: configuredAuth, authority, tenantId: configuredTenantId } = this.connectionSettings ?? {}
197
250
 
198
251
  if (!tenantId) {
199
252
  // No agentic tenant override — delegate to shared utility
200
- return resolveAuthorityUtil(configuredAuth, configuredTenantId)
253
+ return resolveAuthorityUtil(configuredAuth ?? authority, configuredTenantId)
201
254
  }
202
255
 
203
256
  // Agentic override: build a clean base using the override tenant, then replace any
204
257
  // /common or GUID placeholder left in the authority (e.g. from a multi-tenant config)
205
- const base = resolveAuthorityUtil(configuredAuth, tenantId)
258
+ const base = resolveAuthorityUtil(configuredAuth ?? authority, tenantId)
206
259
  const guidPattern = /\/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/
207
260
 
208
261
  if (base.endsWith('/common') || guidPattern.test(base)) {
@@ -257,22 +310,42 @@ export class MsalTokenProvider implements AuthProvider {
257
310
  data.client_info = '2'
258
311
  }
259
312
 
260
- const token = await axios.post(
313
+ const controller = new AbortController()
314
+ const timeoutId = setTimeout(() => {
315
+ controller.abort(createTokenRequestTimeoutError(agenticTokenRequestTimeoutMs))
316
+ }, agenticTokenRequestTimeoutMs)
317
+
318
+ const token = await fetch(
261
319
  url,
262
- data,
263
320
  {
321
+ method: 'POST',
264
322
  headers: {
265
323
  'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
266
- }
324
+ },
325
+ body: new URLSearchParams(data as Record<string, string>).toString(),
326
+ signal: controller.signal
267
327
  }
268
- ).catch((error) => {
269
- logger.error('Error acquiring token: ', error.toJSON())
270
- throw error
328
+ ).then(async (response) => {
329
+ if (!response.ok) {
330
+ const errorBody = await response.text()
331
+ const error = new Error(`Token request failed with status ${response.status}: ${errorBody}`)
332
+ ;(error as any).toJSON = () => ({ status: response.status, body: errorBody })
333
+ throw error
334
+ }
335
+ return response.json() as Promise<{ access_token: string, expires_in: number }>
336
+ }).catch((error) => {
337
+ const resolvedError = isAbortError(error)
338
+ ? (controller.signal.reason instanceof Error ? controller.signal.reason : createTokenRequestTimeoutError(agenticTokenRequestTimeoutMs))
339
+ : error
340
+ logger.error('Error acquiring token: ', resolvedError.toJSON ? resolvedError.toJSON() : resolvedError)
341
+ throw resolvedError
342
+ }).finally(() => {
343
+ clearTimeout(timeoutId)
271
344
  })
272
345
 
273
346
  // capture token, expire local cache 5 minutes early
274
- this._agenticTokenCache.set(cacheKey, token.data.access_token, token.data.expires_in - 300)
275
- return token.data.access_token
347
+ this._agenticTokenCache.set(cacheKey, token.access_token, token.expires_in - 300)
348
+ return token.access_token
276
349
  }
277
350
 
278
351
  public async getAgenticUserToken (tenantId: string, agentAppInstanceId: string, agenticUserId: string, scopes: string[]): Promise<string> {
@@ -303,12 +376,60 @@ export class MsalTokenProvider implements AuthProvider {
303
376
  }
304
377
  logger.debug('getAgenticApplicationToken clientId=%s tenantId=%s agentAppInstanceId=%s', this.connectionSettings.clientId, tenantId, agentAppInstanceId)
305
378
 
379
+ if (this.connectionSettings.authType === AuthType.IdentityProxyManager) {
380
+ let resource: string
381
+ if (!this.connectionSettings.idpmResource) {
382
+ resource = 'api://AzureAdTokenExchange/.default'
383
+ } else if (!URL.canParse(this.connectionSettings.idpmResource)) {
384
+ throw new Error('idpmResource must be a valid absolute URI')
385
+ } else {
386
+ resource = this.connectionSettings.idpmResource
387
+ }
388
+ const msiApp = new ManagedIdentityApplication({
389
+ managedIdentityIdParams: {
390
+ userAssignedClientId: this.connectionSettings.clientId
391
+ },
392
+ system: this.sysOptions
393
+ })
394
+ const tokenResult = await msiApp.acquireToken({ resource })
395
+ if (!tokenResult?.accessToken) {
396
+ throw new Error(`Failed to acquire token via IdentityProxyManager for agent instance: ${agentAppInstanceId}`)
397
+ }
398
+ logger.debug('getAgenticApplicationToken via IdentityProxyManager clientId=%s resource=%s', this.connectionSettings.clientId, resource)
399
+ return tokenResult.accessToken
400
+ }
401
+
306
402
  let clientAssertion
307
403
 
308
- if (this.connectionSettings.WIDAssertionFile !== undefined) {
309
- clientAssertion = fs.readFileSync(this.connectionSettings.WIDAssertionFile as string, 'utf8')
310
- } else if (this.connectionSettings.FICClientId !== undefined) {
311
- clientAssertion = await this.fetchExternalToken(this.connectionSettings.FICClientId as string)
404
+ if (this.connectionSettings.authType) {
405
+ switch (this.connectionSettings.authType) {
406
+ case AuthType.WorkloadIdentity: {
407
+ const tokenFilePath = this.connectionSettings.federatedTokenFile ?? this.connectionSettings.WIDAssertionFile
408
+ if (tokenFilePath === undefined) {
409
+ throw ExceptionHelper.generateException(Error, Errors.WorkloadIdentityTokenFileRequired)
410
+ }
411
+ clientAssertion = fs.readFileSync(tokenFilePath as string, 'utf8')
412
+ break
413
+ }
414
+ case AuthType.FederatedCredentials:
415
+ if (!this.connectionSettings.federatedClientId && !this.connectionSettings.FICClientId) {
416
+ throw ExceptionHelper.generateException(Error, Errors.FICClientIdRequired)
417
+ }
418
+ clientAssertion = await this.fetchExternalToken(this.connectionSettings.federatedClientId as string || this.connectionSettings.FICClientId as string)
419
+ break
420
+ case AuthType.Certificate:
421
+ case AuthType.CertificateSubjectName:
422
+ if (!this.connectionSettings.certPemFile || !this.connectionSettings.certKeyFile) {
423
+ throw ExceptionHelper.generateException(Error, Errors.CertificateFilesRequired)
424
+ }
425
+ clientAssertion = this.getAssertionFromCert(this.connectionSettings)
426
+ break
427
+ }
428
+ } else if (this.connectionSettings.WIDAssertionFile !== undefined) {
429
+ const tokenFilePath = this.connectionSettings.federatedTokenFile ?? this.connectionSettings.WIDAssertionFile
430
+ clientAssertion = fs.readFileSync(tokenFilePath as string, 'utf8')
431
+ } else if (this.connectionSettings.federatedClientId !== undefined || this.connectionSettings.FICClientId !== undefined) {
432
+ clientAssertion = await this.fetchExternalToken(this.connectionSettings.federatedClientId as string || this.connectionSettings.FICClientId as string)
312
433
  } else if (this.connectionSettings.certPemFile !== undefined &&
313
434
  this.connectionSettings.certKeyFile !== undefined) {
314
435
  clientAssertion = this.getAssertionFromCert(this.connectionSettings)
@@ -380,7 +501,7 @@ export class MsalTokenProvider implements AuthProvider {
380
501
  aud: `${this.resolveAuthority(authConfig.tenantId)}/oauth2/v2.0/token`,
381
502
  iss: authConfig.clientId,
382
503
  sub: authConfig.clientId,
383
- jti: v4(),
504
+ jti: randomUUID(),
384
505
  nbf: now,
385
506
  iat: now,
386
507
  exp: now + 600, // 10 minutes
@@ -415,6 +536,22 @@ export class MsalTokenProvider implements AuthProvider {
415
536
  return token?.accessToken
416
537
  }
417
538
 
539
+ /**
540
+ * Acquires a token using a system-assigned identity.
541
+ * @param authConfig The authentication configuration.
542
+ * @param scope The scope for the token.
543
+ * @returns A promise that resolves to the access token.
544
+ */
545
+ private async acquireTokenWithSystemAssignedIdentity (authConfig: AuthConfiguration, scope: string) {
546
+ const mia = new ManagedIdentityApplication({
547
+ system: this.sysOptions
548
+ })
549
+ const token = await mia.acquireToken({
550
+ resource: scope
551
+ })
552
+ return token?.accessToken
553
+ }
554
+
418
555
  /**
419
556
  * Acquires a token using a certificate.
420
557
  * @param authConfig The authentication configuration.
@@ -440,7 +577,7 @@ export class MsalTokenProvider implements AuthProvider {
440
577
  const cca = new ConfidentialClientApplication({
441
578
  auth: {
442
579
  clientId: authConfig.clientId || '',
443
- authority: `${authConfig.authority}/${authConfig.tenantId || 'botframework.com'}`,
580
+ authority: `${authConfig.authorityEndpoint ?? authConfig.authority}/${authConfig.tenantId || 'botframework.com'}`,
444
581
  clientCertificate: {
445
582
  privateKey: privateKey as string,
446
583
  thumbprint: pubKeyObject.fingerprint.replaceAll(':', ''),
@@ -451,7 +588,7 @@ export class MsalTokenProvider implements AuthProvider {
451
588
  })
452
589
  const token = await cca.acquireTokenByClientCredential({
453
590
  scopes: [`${scope}/.default`],
454
- correlationId: v4(),
591
+ correlationId: randomUUID(),
455
592
  azureRegion: authConfig.azureRegion
456
593
  })
457
594
  if (!token?.accessToken) {
@@ -470,14 +607,14 @@ export class MsalTokenProvider implements AuthProvider {
470
607
  const cca = new ConfidentialClientApplication({
471
608
  auth: {
472
609
  clientId: authConfig.clientId as string,
473
- authority: `${authConfig.authority}/${authConfig.tenantId || 'botframework.com'}`,
610
+ authority: `${authConfig.authorityEndpoint ?? authConfig.authority}/${authConfig.tenantId || 'botframework.com'}`,
474
611
  clientSecret: authConfig.clientSecret
475
612
  },
476
613
  system: this.sysOptions
477
614
  })
478
615
  const token = await cca.acquireTokenByClientCredential({
479
616
  scopes: [`${scope}/.default`],
480
- correlationId: v4(),
617
+ correlationId: randomUUID(),
481
618
  azureRegion: authConfig.azureRegion
482
619
  })
483
620
  if (!token?.accessToken) {
@@ -494,11 +631,11 @@ export class MsalTokenProvider implements AuthProvider {
494
631
  */
495
632
  private async acquireAccessTokenViaFIC (authConfig: AuthConfiguration, scope: string) : Promise<string> {
496
633
  const scopes = [`${scope}/.default`]
497
- const clientAssertion = await this.fetchExternalToken(authConfig.FICClientId as string)
634
+ const clientAssertion = await this.fetchExternalToken(authConfig.federatedClientId as string || authConfig.FICClientId as string)
498
635
  const cca = new ConfidentialClientApplication({
499
636
  auth: {
500
637
  clientId: authConfig.clientId as string,
501
- authority: `${authConfig.authority}/${authConfig.tenantId}`,
638
+ authority: `${authConfig.authorityEndpoint ?? authConfig.authority}/${authConfig.tenantId}`,
502
639
  clientAssertion
503
640
  },
504
641
  system: this.sysOptions
@@ -519,7 +656,8 @@ export class MsalTokenProvider implements AuthProvider {
519
656
  */
520
657
  private async acquireAccessTokenViaWID (authConfig: AuthConfiguration, scope: string) : Promise<string> {
521
658
  const scopes = [`${scope}/.default`]
522
- const clientAssertion = fs.readFileSync(authConfig.WIDAssertionFile as string, 'utf8')
659
+ const tokenFilePath = authConfig.federatedTokenFile ?? authConfig.WIDAssertionFile
660
+ const clientAssertion = fs.readFileSync(tokenFilePath as string, 'utf8')
523
661
  const cca = new ConfidentialClientApplication({
524
662
  auth: {
525
663
  clientId: authConfig.clientId as string,