@microsoft/agents-hosting 1.6.0-beta.9.gce9d8facd2 → 1.7.0-beta.1.g8bcd4f11a7
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/dist/package.json +4 -9
- package/dist/src/agent-client/agentClient.js +2 -2
- package/dist/src/agent-client/agentClient.js.map +1 -1
- package/dist/src/agent-client/agentResponseHandler.js +2 -2
- package/dist/src/agent-client/agentResponseHandler.js.map +1 -1
- package/dist/src/app/agentApplication.js +28 -2
- package/dist/src/app/agentApplication.js.map +1 -1
- package/dist/src/app/agentApplicationOptions.d.ts +10 -0
- package/dist/src/app/attachmentDownloader.js +5 -10
- package/dist/src/app/attachmentDownloader.js.map +1 -1
- package/dist/src/app/auth/authorizationManager.d.ts +4 -0
- package/dist/src/app/auth/authorizationManager.js +94 -67
- package/dist/src/app/auth/authorizationManager.js.map +1 -1
- package/dist/src/app/auth/handlers/azureBotAuthorization.js +2 -2
- package/dist/src/app/auth/handlers/azureBotAuthorization.js.map +1 -1
- package/dist/src/app/proactive/createConversationOptionsBuilder.js +10 -6
- package/dist/src/app/proactive/createConversationOptionsBuilder.js.map +1 -1
- package/dist/src/app/proactive/proactive.d.ts +1 -0
- package/dist/src/app/proactive/proactive.js +30 -15
- package/dist/src/app/proactive/proactive.js.map +1 -1
- package/dist/src/app/streaming/streamingResponse.d.ts +11 -0
- package/dist/src/app/streaming/streamingResponse.js +21 -0
- package/dist/src/app/streaming/streamingResponse.js.map +1 -1
- package/dist/src/app/teamsAttachmentDownloader.js +6 -14
- package/dist/src/app/teamsAttachmentDownloader.js.map +1 -1
- package/dist/src/auth/MemoryCache.d.ts +2 -1
- package/dist/src/auth/MemoryCache.js +7 -1
- package/dist/src/auth/MemoryCache.js.map +1 -1
- package/dist/src/auth/authConfiguration.d.ts +2 -143
- package/dist/src/auth/authConfiguration.js +336 -257
- package/dist/src/auth/authConfiguration.js.map +1 -1
- package/dist/src/auth/authConstants.d.ts +7 -7
- package/dist/src/auth/authConstants.js.map +1 -1
- package/dist/src/auth/connectionManager.d.ts +92 -0
- package/dist/src/auth/{msalConnectionManager.js → connectionManager.js} +48 -33
- package/dist/src/auth/connectionManager.js.map +1 -0
- package/dist/src/auth/index.d.ts +5 -3
- package/dist/src/auth/index.js +5 -3
- package/dist/src/auth/index.js.map +1 -1
- package/dist/src/auth/jwt-middleware.d.ts +6 -0
- package/dist/src/auth/jwt-middleware.js +34 -2
- package/dist/src/auth/jwt-middleware.js.map +1 -1
- package/dist/src/auth/msal/msalConnectionManager.d.ts +17 -0
- package/dist/src/auth/msal/msalConnectionManager.js +50 -0
- package/dist/src/auth/msal/msalConnectionManager.js.map +1 -0
- package/dist/src/auth/msal/msalConnectionSettings.d.ts +68 -0
- package/dist/src/auth/msal/msalConnectionSettings.js +7 -0
- package/dist/src/auth/msal/msalConnectionSettings.js.map +1 -0
- package/dist/src/auth/{msalTokenCredential.d.ts → msal/msalTokenCredential.d.ts} +1 -1
- package/dist/src/auth/{msalTokenCredential.js → msal/msalTokenCredential.js} +2 -2
- package/dist/src/auth/msal/msalTokenCredential.js.map +1 -0
- package/dist/src/auth/{msalTokenProvider.d.ts → msal/msalTokenProvider.d.ts} +30 -3
- package/dist/src/auth/msal/msalTokenProvider.js +733 -0
- package/dist/src/auth/msal/msalTokenProvider.js.map +1 -0
- package/dist/src/auth/settings.d.ts +336 -0
- package/dist/src/auth/settings.js +202 -0
- package/dist/src/auth/settings.js.map +1 -0
- package/dist/src/auth/sidecar/sidecarAuthProvider.d.ts +74 -0
- package/dist/src/auth/sidecar/sidecarAuthProvider.js +181 -0
- package/dist/src/auth/sidecar/sidecarAuthProvider.js.map +1 -0
- package/dist/src/auth/sidecar/sidecarConnectionSettings.d.ts +65 -0
- package/dist/src/auth/sidecar/sidecarConnectionSettings.js +7 -0
- package/dist/src/auth/sidecar/sidecarConnectionSettings.js.map +1 -0
- package/dist/src/auth/sidecar/sidecarHttpClient.d.ts +95 -0
- package/dist/src/auth/sidecar/sidecarHttpClient.js +406 -0
- package/dist/src/auth/sidecar/sidecarHttpClient.js.map +1 -0
- package/dist/src/auth/sidecar/sidecarModels.d.ts +110 -0
- package/dist/src/auth/sidecar/sidecarModels.js +48 -0
- package/dist/src/auth/sidecar/sidecarModels.js.map +1 -0
- package/dist/src/auth/sidecar/sidecarTokenExpiry.d.ts +13 -0
- package/dist/src/auth/sidecar/sidecarTokenExpiry.js +39 -0
- package/dist/src/auth/sidecar/sidecarTokenExpiry.js.map +1 -0
- package/dist/src/cloudAdapter.d.ts +58 -1
- package/dist/src/cloudAdapter.js +233 -53
- package/dist/src/cloudAdapter.js.map +1 -1
- package/dist/src/connector-client/connectorClient.d.ts +12 -8
- package/dist/src/connector-client/connectorClient.js +99 -82
- package/dist/src/connector-client/connectorClient.js.map +1 -1
- package/dist/src/errorHelper.js +181 -7
- package/dist/src/errorHelper.js.map +1 -1
- package/dist/src/getProductInfo.d.ts +23 -0
- package/dist/src/getProductInfo.js +71 -1
- package/dist/src/getProductInfo.js.map +1 -1
- package/dist/src/headerPropagation.d.ts +17 -2
- package/dist/src/headerPropagation.js +46 -24
- package/dist/src/headerPropagation.js.map +1 -1
- package/dist/src/httpClient.d.ts +60 -0
- package/dist/src/httpClient.js +173 -0
- package/dist/src/httpClient.js.map +1 -0
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.js +8 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/oauth/userTokenClient.d.ts +17 -4
- package/dist/src/oauth/userTokenClient.js +119 -80
- package/dist/src/oauth/userTokenClient.js.map +1 -1
- package/dist/src/observability/traces.d.ts +11 -4
- package/dist/src/observability/traces.js +39 -7
- package/dist/src/observability/traces.js.map +1 -1
- package/dist/src/utils/env.d.ts +50 -0
- package/dist/src/utils/env.js +113 -0
- package/dist/src/utils/env.js.map +1 -0
- package/dist/src/utils.d.ts +10 -0
- package/dist/src/utils.js +18 -0
- package/dist/src/utils.js.map +1 -0
- package/package.json +4 -9
- package/src/agent-client/agentClient.ts +2 -2
- package/src/agent-client/agentResponseHandler.ts +2 -2
- package/src/app/agentApplication.ts +30 -3
- package/src/app/agentApplicationOptions.ts +11 -0
- package/src/app/attachmentDownloader.ts +6 -8
- package/src/app/auth/authorizationManager.ts +84 -41
- package/src/app/auth/handlers/azureBotAuthorization.ts +2 -2
- package/src/app/proactive/createConversationOptionsBuilder.ts +8 -4
- package/src/app/proactive/proactive.ts +39 -23
- package/src/app/streaming/streamingResponse.ts +24 -1
- package/src/app/teamsAttachmentDownloader.ts +7 -11
- package/src/auth/MemoryCache.ts +7 -1
- package/src/auth/authConfiguration.ts +350 -356
- package/src/auth/authConstants.ts +7 -7
- package/src/auth/{msalConnectionManager.ts → connectionManager.ts} +65 -44
- package/src/auth/index.ts +5 -3
- package/src/auth/jwt-middleware.ts +32 -2
- package/src/auth/msal/msalConnectionManager.ts +55 -0
- package/src/auth/msal/msalConnectionSettings.ts +79 -0
- package/src/auth/{msalTokenCredential.ts → msal/msalTokenCredential.ts} +2 -1
- package/src/auth/msal/msalTokenProvider.ts +881 -0
- package/src/auth/settings.ts +378 -0
- package/src/auth/sidecar/sidecarAuthProvider.ts +234 -0
- package/src/auth/sidecar/sidecarConnectionSettings.ts +72 -0
- package/src/auth/sidecar/sidecarHttpClient.ts +443 -0
- package/src/auth/sidecar/sidecarModels.ts +153 -0
- package/src/auth/sidecar/sidecarTokenExpiry.ts +35 -0
- package/src/cloudAdapter.ts +292 -13
- package/src/connector-client/connectorClient.ts +116 -94
- package/src/errorHelper.ts +206 -7
- package/src/getProductInfo.ts +79 -1
- package/src/headerPropagation.ts +55 -23
- package/src/httpClient.ts +223 -0
- package/src/index.ts +6 -2
- package/src/oauth/userTokenClient.ts +137 -84
- package/src/observability/traces.ts +39 -8
- package/src/utils/env.ts +105 -0
- package/src/utils.ts +14 -0
- package/dist/src/auth/msalConnectionManager.d.ts +0 -64
- package/dist/src/auth/msalConnectionManager.js.map +0 -1
- package/dist/src/auth/msalTokenCredential.js.map +0 -1
- package/dist/src/auth/msalTokenProvider.js +0 -485
- package/dist/src/auth/msalTokenProvider.js.map +0 -1
- package/src/auth/msalTokenProvider.ts +0 -562
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
export const ApxLocalScope = 'c16e153d-5d2b-4c21-b7f4-b05ee5d516f1/.default'
|
|
6
|
-
export const ApxDevScope = '0d94caae-b412-4943-8a68-83135ad6d35f/.default'
|
|
7
|
-
export const ApxProductionScope = '5a807f24-c9de-44ee-a3a7-329e88a00ffc/.default'
|
|
8
|
-
export const ApxGCCScope = 'c9475445-9789-4fef-9ec5-cde4a9bcd446/.default'
|
|
9
|
-
export const ApxGCCHScope = '6f669b9e-7701-4e2b-b624-82c9207fde26/.default'
|
|
10
|
-
export const ApxDoDScope = '0a069c81-8c7c-4712-886b-9c542d673ffb/.default'
|
|
11
|
-
export const ApxGallatinScope = 'bd004c8e-5acf-4c48-8570-4e7d46b2f63b/.default'
|
|
5
|
+
export const ApxLocalScope: string = 'c16e153d-5d2b-4c21-b7f4-b05ee5d516f1/.default'
|
|
6
|
+
export const ApxDevScope: string = '0d94caae-b412-4943-8a68-83135ad6d35f/.default'
|
|
7
|
+
export const ApxProductionScope: string = '5a807f24-c9de-44ee-a3a7-329e88a00ffc/.default'
|
|
8
|
+
export const ApxGCCScope: string = 'c9475445-9789-4fef-9ec5-cde4a9bcd446/.default'
|
|
9
|
+
export const ApxGCCHScope: string = '6f669b9e-7701-4e2b-b624-82c9207fde26/.default'
|
|
10
|
+
export const ApxDoDScope: string = '0a069c81-8c7c-4712-886b-9c542d673ffb/.default'
|
|
11
|
+
export const ApxGallatinScope: string = 'bd004c8e-5acf-4c48-8570-4e7d46b2f63b/.default'
|
|
@@ -3,28 +3,58 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { Activity, RoleTypes } from '@microsoft/agents-activity'
|
|
7
|
-
import { debug } from '@microsoft/agents-telemetry'
|
|
8
|
-
import { AuthConfiguration,
|
|
6
|
+
import { Activity, ExceptionHelper, RoleTypes } from '@microsoft/agents-activity'
|
|
7
|
+
import { debug, redactString } from '@microsoft/agents-telemetry'
|
|
8
|
+
import { AuthConfiguration, AuthType, resolveAuthType } from './authConfiguration'
|
|
9
9
|
import { Connections } from './connections'
|
|
10
|
-
import {
|
|
10
|
+
import { AuthProvider } from './authProvider'
|
|
11
|
+
import { MsalTokenProvider } from './msal/msalTokenProvider'
|
|
12
|
+
import { SidecarAuthProvider } from './sidecar/sidecarAuthProvider'
|
|
11
13
|
import { JwtPayload } from 'jsonwebtoken'
|
|
14
|
+
import { Errors } from '../errorHelper'
|
|
15
|
+
import type { ConnectionMapItem } from './settings'
|
|
12
16
|
|
|
13
17
|
const logger = debug('agents:authorization:connections')
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Factory function that creates an {@link AuthProvider} instance from a connection's
|
|
21
|
+
* {@link AuthConfiguration}.
|
|
22
|
+
*/
|
|
23
|
+
export type AuthProviderFactory = (config: AuthConfiguration) => AuthProvider
|
|
20
24
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Default {@link AuthProviderFactory} that dispatches per-connection by `authType`: connections with
|
|
27
|
+
* `authType` set to `EntraAuthSideCar` use {@link SidecarAuthProvider}; all others use
|
|
28
|
+
* {@link MsalTokenProvider}.
|
|
29
|
+
* @param config The connection authentication configuration.
|
|
30
|
+
* @returns The auth provider for the connection.
|
|
31
|
+
*/
|
|
32
|
+
export const defaultAuthProviderFactory: AuthProviderFactory = (config: AuthConfiguration): AuthProvider =>
|
|
33
|
+
config?.authType === AuthType.EntraAuthSideCar
|
|
34
|
+
? new SidecarAuthProvider(config)
|
|
35
|
+
: new MsalTokenProvider(config)
|
|
26
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Generic, provider-agnostic connection manager. Dispatches connections to any {@link AuthProvider}
|
|
39
|
+
* implementation produced by the supplied {@link AuthProviderFactory}, while owning the
|
|
40
|
+
* provider-independent connection routing logic (audience matching, service URL dispatch,
|
|
41
|
+
* `altBlueprintConnectionName` handling, default connection resolution).
|
|
42
|
+
*/
|
|
43
|
+
export class ConnectionManager implements Connections {
|
|
44
|
+
protected _connections: Map<string, AuthProvider>
|
|
45
|
+
protected _connectionsMap: ConnectionMapItem[]
|
|
46
|
+
protected _serviceConnectionConfiguration: AuthConfiguration
|
|
47
|
+
protected static readonly DEFAULT_CONNECTION = 'serviceConnection'
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Creates a new {@link ConnectionManager}.
|
|
51
|
+
* @param providerFactory Factory used to instantiate an {@link AuthProvider} for each connection.
|
|
52
|
+
* @param connectionsConfigurations Map of connection names to their authentication configurations.
|
|
53
|
+
* @param connectionsMap Map items used to route activities to connections.
|
|
54
|
+
* @param configuration Fallback authentication configuration (used when the above are empty).
|
|
55
|
+
*/
|
|
27
56
|
constructor (
|
|
57
|
+
providerFactory: AuthProviderFactory = defaultAuthProviderFactory,
|
|
28
58
|
connectionsConfigurations: Map<string, AuthConfiguration> = new Map(),
|
|
29
59
|
connectionsMap: ConnectionMapItem[] = [],
|
|
30
60
|
configuration: AuthConfiguration = {}) {
|
|
@@ -35,23 +65,16 @@ export class MsalConnectionManager implements Connections {
|
|
|
35
65
|
const providedConnections = connectionsConfigurations.size > 0 ? connectionsConfigurations : (configuration.connections || new Map())
|
|
36
66
|
|
|
37
67
|
for (const [name, config] of providedConnections) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (name === MsalConnectionManager.DEFAULT_CONNECTION) {
|
|
68
|
+
this._connections.set(name, providerFactory(config))
|
|
69
|
+
if (name === ConnectionManager.DEFAULT_CONNECTION) {
|
|
41
70
|
this._serviceConnectionConfiguration = config
|
|
42
71
|
}
|
|
43
72
|
}
|
|
44
73
|
|
|
45
74
|
for (const [name, provider] of this._connections.entries()) {
|
|
46
75
|
const cfg = provider.connectionSettings
|
|
47
|
-
const authType = cfg
|
|
48
|
-
|
|
49
|
-
: cfg?.clientSecret
|
|
50
|
-
? 'clientSecret'
|
|
51
|
-
: cfg?.WIDAssertionFile || cfg?.FICClientId
|
|
52
|
-
? 'workloadIdentity'
|
|
53
|
-
: 'none'
|
|
54
|
-
logger.debug('connection "%s" clientId=%s tenantId=%s authType=%s', name, cfg?.clientId ?? '<none>', cfg?.tenantId ?? '<none>', authType)
|
|
76
|
+
const authType = resolveAuthType(cfg)
|
|
77
|
+
logger.debug('connection "%s" clientId=%s tenantId=%s authType=%s', name, redactString(cfg?.clientId, true) ?? '<none>', redactString(cfg?.tenantId, true) ?? '<none>', authType)
|
|
55
78
|
}
|
|
56
79
|
|
|
57
80
|
for (const item of this._connectionsMap) {
|
|
@@ -64,10 +87,10 @@ export class MsalConnectionManager implements Connections {
|
|
|
64
87
|
* @param connectionName The name of the connection.
|
|
65
88
|
* @returns The OAuth connection for the agent.
|
|
66
89
|
*/
|
|
67
|
-
getConnection (connectionName: string):
|
|
90
|
+
getConnection (connectionName: string): AuthProvider {
|
|
68
91
|
const conn = this._connections.get(connectionName)
|
|
69
92
|
if (!conn) {
|
|
70
|
-
throw
|
|
93
|
+
throw ExceptionHelper.generateException(Error, Errors.ConnectionNotFound, undefined, { connectionName })
|
|
71
94
|
}
|
|
72
95
|
return this.applyConnectionDefaults(conn)
|
|
73
96
|
}
|
|
@@ -76,9 +99,9 @@ export class MsalConnectionManager implements Connections {
|
|
|
76
99
|
* Get the default OAuth connection for the agent.
|
|
77
100
|
* @returns The default OAuth connection for the agent.
|
|
78
101
|
*/
|
|
79
|
-
getDefaultConnection ():
|
|
102
|
+
getDefaultConnection (): AuthProvider {
|
|
80
103
|
if (this._connections.size === 0) {
|
|
81
|
-
throw
|
|
104
|
+
throw ExceptionHelper.generateException(Error, Errors.NoConnectionsFoundInConfiguration)
|
|
82
105
|
}
|
|
83
106
|
|
|
84
107
|
// Return the wildcard map item instance.
|
|
@@ -88,7 +111,7 @@ export class MsalConnectionManager implements Connections {
|
|
|
88
111
|
}
|
|
89
112
|
}
|
|
90
113
|
|
|
91
|
-
const conn = this._connections.values().next().value as
|
|
114
|
+
const conn = this._connections.values().next().value as AuthProvider
|
|
92
115
|
|
|
93
116
|
return this.applyConnectionDefaults(conn)
|
|
94
117
|
}
|
|
@@ -111,9 +134,9 @@ export class MsalConnectionManager implements Connections {
|
|
|
111
134
|
* ServiceUrl is: A regex to match with, or "*" for any serviceUrl value.
|
|
112
135
|
* Connection is: A name in the 'Connections' list.
|
|
113
136
|
*/
|
|
114
|
-
getTokenProvider (identity: JwtPayload, serviceUrl: string):
|
|
137
|
+
getTokenProvider (identity: JwtPayload, serviceUrl: string): AuthProvider {
|
|
115
138
|
if (!identity) {
|
|
116
|
-
throw
|
|
139
|
+
throw ExceptionHelper.generateException(Error, Errors.IdentityRequiredForTokenProvider)
|
|
117
140
|
}
|
|
118
141
|
|
|
119
142
|
let audience
|
|
@@ -123,7 +146,7 @@ export class MsalConnectionManager implements Connections {
|
|
|
123
146
|
audience = identity.aud
|
|
124
147
|
}
|
|
125
148
|
|
|
126
|
-
if (!audience || !serviceUrl) throw
|
|
149
|
+
if (!audience || !serviceUrl) throw ExceptionHelper.generateException(Error, Errors.AudienceAndServiceUrlRequiredForTokenProvider)
|
|
127
150
|
|
|
128
151
|
if (this._connectionsMap.length === 0) {
|
|
129
152
|
logger.debug('no connectionsMap, using default connection for serviceUrl=%s', serviceUrl)
|
|
@@ -151,7 +174,7 @@ export class MsalConnectionManager implements Connections {
|
|
|
151
174
|
}
|
|
152
175
|
}
|
|
153
176
|
}
|
|
154
|
-
throw
|
|
177
|
+
throw ExceptionHelper.generateException(Error, Errors.NoConnectionForAudienceAndServiceUrl, undefined, { audience: String(audience), serviceUrl })
|
|
155
178
|
}
|
|
156
179
|
|
|
157
180
|
/**
|
|
@@ -160,7 +183,7 @@ export class MsalConnectionManager implements Connections {
|
|
|
160
183
|
* @param activity The activity.
|
|
161
184
|
* @returns The TokenProvider for the connection.
|
|
162
185
|
*/
|
|
163
|
-
getTokenProviderFromActivity (identity: JwtPayload, activity: Activity):
|
|
186
|
+
getTokenProviderFromActivity (identity: JwtPayload, activity: Activity): AuthProvider {
|
|
164
187
|
let connection = this.getTokenProvider(identity, activity.serviceUrl || '')
|
|
165
188
|
|
|
166
189
|
// This is for the case where the Agentic BlueprintId is not the same as the AppId
|
|
@@ -183,15 +206,13 @@ export class MsalConnectionManager implements Connections {
|
|
|
183
206
|
return this._serviceConnectionConfiguration
|
|
184
207
|
}
|
|
185
208
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
]
|
|
194
|
-
}
|
|
209
|
+
/**
|
|
210
|
+
* Applies provider-specific defaults to a resolved connection before returning it. The generic
|
|
211
|
+
* base performs no mutation; provider-specific managers may override this.
|
|
212
|
+
* @param conn The resolved auth provider.
|
|
213
|
+
* @returns The auth provider, possibly with defaults applied.
|
|
214
|
+
*/
|
|
215
|
+
protected applyConnectionDefaults (conn: AuthProvider): AuthProvider {
|
|
195
216
|
return conn
|
|
196
217
|
}
|
|
197
218
|
}
|
package/src/auth/index.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export * from './authConfiguration'
|
|
2
2
|
export * from './authConstants'
|
|
3
3
|
export * from './authProvider'
|
|
4
|
-
export * from './msalTokenProvider'
|
|
4
|
+
export * from './msal/msalTokenProvider'
|
|
5
5
|
export * from './request'
|
|
6
|
-
export * from './msalTokenCredential'
|
|
7
|
-
export * from './
|
|
6
|
+
export * from './msal/msalTokenCredential'
|
|
7
|
+
export * from './connectionManager'
|
|
8
|
+
export * from './msal/msalConnectionManager'
|
|
9
|
+
export * from './sidecar/sidecarAuthProvider'
|
|
@@ -11,6 +11,15 @@ import jwt, { JwtHeader, JwtPayload, SignCallback, GetPublicKeyOrSecret } from '
|
|
|
11
11
|
import { debug } from '@microsoft/agents-telemetry'
|
|
12
12
|
|
|
13
13
|
const logger = debug('agents:jwt-middleware')
|
|
14
|
+
const jwksClients = new Map<string, JwksClient>()
|
|
15
|
+
const maxJwksClients = 100
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Clears process-wide JWKS clients.
|
|
19
|
+
*/
|
|
20
|
+
export function clearJwksClients (): void {
|
|
21
|
+
jwksClients.clear()
|
|
22
|
+
}
|
|
14
23
|
|
|
15
24
|
/**
|
|
16
25
|
* Builds the JWKS URI for the given token issuer and auth configuration.
|
|
@@ -21,7 +30,27 @@ const logger = debug('agents:jwt-middleware')
|
|
|
21
30
|
export function buildJwksUri (iss: string, authConfig: AuthConfiguration): string {
|
|
22
31
|
return iss === 'https://api.botframework.com'
|
|
23
32
|
? 'https://login.botframework.com/v1/.well-known/keys'
|
|
24
|
-
: `${resolveAuthority(authConfig.authority, authConfig.tenantId)}/discovery/v2.0/keys`
|
|
33
|
+
: `${resolveAuthority(authConfig.authorityEndpoint ?? authConfig.authority, authConfig.tenantId)}/discovery/v2.0/keys`
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function getJwksClient (jwksUri: string): JwksClient {
|
|
37
|
+
// Check if a client for this JWKS URI already exists in the cache.
|
|
38
|
+
let client = jwksClients.get(jwksUri)
|
|
39
|
+
if (!client) {
|
|
40
|
+
client = jwksRsa({ jwksUri })
|
|
41
|
+
jwksClients.set(jwksUri, client)
|
|
42
|
+
while (jwksClients.size > maxJwksClients) {
|
|
43
|
+
const oldestKey = jwksClients.keys().next().value
|
|
44
|
+
if (oldestKey === undefined) {
|
|
45
|
+
break
|
|
46
|
+
}
|
|
47
|
+
jwksClients.delete(oldestKey)
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
jwksClients.delete(jwksUri)
|
|
51
|
+
jwksClients.set(jwksUri, client)
|
|
52
|
+
}
|
|
53
|
+
return client
|
|
25
54
|
}
|
|
26
55
|
|
|
27
56
|
/**
|
|
@@ -55,9 +84,10 @@ const verifyToken = async (raw: string, config: AuthConfiguration): Promise<JwtP
|
|
|
55
84
|
const jwksUri = buildJwksUri(payload.iss as string, authConfig)
|
|
56
85
|
|
|
57
86
|
logger.debug(`fetching keys from ${jwksUri}`)
|
|
58
|
-
const jwksClient
|
|
87
|
+
const jwksClient = getJwksClient(jwksUri)
|
|
59
88
|
|
|
60
89
|
const getKey: GetPublicKeyOrSecret = (header: JwtHeader, callback: SignCallback) => {
|
|
90
|
+
// Retrieve the public, issuer-wide signing key from the JWKS endpoint using the kid from the token header.
|
|
61
91
|
jwksClient.getSigningKey(header.kid, (err: Error | null, key: SigningKey | undefined): void => {
|
|
62
92
|
if (err) {
|
|
63
93
|
logger.error('jwksClient.getSigningKey ', JSON.stringify(err))
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { AuthConfiguration, resolveAuthority } from '../authConfiguration'
|
|
7
|
+
import type { ConnectionMapItem } from '../settings'
|
|
8
|
+
import { AuthProvider } from '../authProvider'
|
|
9
|
+
import { ConnectionManager, defaultAuthProviderFactory } from '../connectionManager'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Connection manager backed by MSAL (and, for `EntraAuthSideCar` connections, the Entra sidecar
|
|
13
|
+
* provider). A thin convenience subclass of {@link ConnectionManager} that supplies the default
|
|
14
|
+
* provider factory and applies MSAL-specific connection defaults.
|
|
15
|
+
*/
|
|
16
|
+
export class MsalConnectionManager extends ConnectionManager {
|
|
17
|
+
constructor (
|
|
18
|
+
connectionsConfigurations: Map<string, AuthConfiguration> = new Map(),
|
|
19
|
+
connectionsMap: ConnectionMapItem[] = [],
|
|
20
|
+
configuration: AuthConfiguration = {}) {
|
|
21
|
+
super(defaultAuthProviderFactory, connectionsConfigurations, connectionsMap, configuration)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
protected applyConnectionDefaults (conn: AuthProvider): AuthProvider {
|
|
25
|
+
if (conn.connectionSettings) {
|
|
26
|
+
conn.connectionSettings.authorityEndpoint ??= conn.connectionSettings.authority || 'https://login.microsoftonline.com'
|
|
27
|
+
conn.connectionSettings.authority ??= conn.connectionSettings.authorityEndpoint
|
|
28
|
+
conn.connectionSettings.issuers ??= [
|
|
29
|
+
'https://api.botframework.com',
|
|
30
|
+
`${resolveAuthority('https://sts.windows.net', conn.connectionSettings.tenantId)}/`,
|
|
31
|
+
`${resolveAuthority(conn.connectionSettings.authorityEndpoint, conn.connectionSettings.tenantId)}/v2.0`
|
|
32
|
+
]
|
|
33
|
+
// For backward compatibility
|
|
34
|
+
if (conn.connectionSettings.federatedClientId) {
|
|
35
|
+
conn.connectionSettings.FICClientId = conn.connectionSettings.federatedClientId
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (conn.connectionSettings.scopes?.length) {
|
|
39
|
+
conn.connectionSettings.scope = conn.connectionSettings.scopes?.[0]
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (conn.connectionSettings.authorityEndpoint) {
|
|
43
|
+
conn.connectionSettings.authority = conn.connectionSettings.authorityEndpoint
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// .NET parity alias: keep altBlueprintConnectionName and alternateBlueprintConnectionName in sync.
|
|
47
|
+
conn.connectionSettings.altBlueprintConnectionName ??= conn.connectionSettings.alternateBlueprintConnectionName
|
|
48
|
+
if (conn.connectionSettings.altBlueprintConnectionName) {
|
|
49
|
+
conn.connectionSettings.alternateBlueprintConnectionName = conn.connectionSettings.altBlueprintConnectionName
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return conn
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ConnectionSettingsBase } from '../settings'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Connection settings for the MSAL-backed authentication providers (the default providers used for
|
|
10
|
+
* every {@link AuthType} except `EntraAuthSideCar`).
|
|
11
|
+
*
|
|
12
|
+
* @remarks
|
|
13
|
+
* Mirrors the .NET `Microsoft.Agents.Authentication.Msal.Model.ConnectionSettings` class. Node.js uses
|
|
14
|
+
* PEM certificate files (`certPemFile`/`certKeyFile`) rather than the Windows certificate store, so the
|
|
15
|
+
* .NET `CertThumbprint`/`CertSubjectName`/`CertStoreName`/`ValidCertificateOnly` settings have no JS
|
|
16
|
+
* equivalent; all other MSAL properties map one-to-one.
|
|
17
|
+
*/
|
|
18
|
+
export interface MsalConnectionSettings extends ConnectionSettingsBase {
|
|
19
|
+
/**
|
|
20
|
+
* The client secret for the authentication configuration.
|
|
21
|
+
*/
|
|
22
|
+
clientSecret?: string
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The path to the certificate PEM file.
|
|
26
|
+
*/
|
|
27
|
+
certPemFile?: string
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The path to the certificate key file.
|
|
31
|
+
*/
|
|
32
|
+
certKeyFile?: string
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Indicates whether to send the X5C param or not (for SNI authentication).
|
|
36
|
+
*/
|
|
37
|
+
sendX5C?: boolean
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @deprecated Use federatedClientId instead.
|
|
41
|
+
*
|
|
42
|
+
* The FIC (First-Party Integration Channel) client ID.
|
|
43
|
+
*/
|
|
44
|
+
FICClientId?: string
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @deprecated Use `authType` set to `'WorkloadIdentity'` and `federatedTokenFile` instead.
|
|
48
|
+
*
|
|
49
|
+
* The path to K8s provided token.
|
|
50
|
+
*/
|
|
51
|
+
WIDAssertionFile?: string
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The Azure region for ESTS-R regional token acquisition (e.g. 'westus', 'eastus').
|
|
55
|
+
* When set, MSAL routes token requests to the specified regional endpoint.
|
|
56
|
+
* See https://learn.microsoft.com/en-us/entra/msal/javascript/node/regional-authorities for details.
|
|
57
|
+
*/
|
|
58
|
+
azureRegion?: string
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The path to the federated token file used for Workload Identity authentication.
|
|
62
|
+
*/
|
|
63
|
+
federatedTokenFile?: string
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Sets the resource URL for Identity Proxy Manager (IDPM).
|
|
67
|
+
*
|
|
68
|
+
* @remarks
|
|
69
|
+
* Set this to the appropriate resource identifier when the application is running in an environment,
|
|
70
|
+
* such as a Foundry container, that exposes Managed Identity through a container-specific IMDS endpoint.
|
|
71
|
+
* This setting is only meaningful when using Identity Proxy Manager (AuthType.IdentityProxyManager) for authentication.
|
|
72
|
+
*/
|
|
73
|
+
idpmResource?: string
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* The federated client ID for the authentication configuration, used for workload identity federation scenarios.
|
|
77
|
+
*/
|
|
78
|
+
federatedClientId?: string
|
|
79
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { GetTokenOptions, TokenCredential } from '@azure/core-auth'
|
|
2
|
-
import { AuthConfiguration
|
|
2
|
+
import { AuthConfiguration } from '../authConfiguration'
|
|
3
|
+
import { MsalTokenProvider } from './msalTokenProvider'
|
|
3
4
|
import { debug } from '@microsoft/agents-telemetry'
|
|
4
5
|
|
|
5
6
|
const logger = debug('agents:msal')
|