@microsoft/agents-hosting 1.1.0-alpha.5 → 1.1.0-alpha.75

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/dist/package.json +10 -6
  2. package/dist/src/activityWireCompat.d.ts +1 -1
  3. package/dist/src/activityWireCompat.js +11 -3
  4. package/dist/src/activityWireCompat.js.map +1 -1
  5. package/dist/src/agent-client/agentClient.js +7 -3
  6. package/dist/src/agent-client/agentClient.js.map +1 -1
  7. package/dist/src/agent-client/agentResponseHandler.js +6 -2
  8. package/dist/src/agent-client/agentResponseHandler.js.map +1 -1
  9. package/dist/src/app/agentApplication.d.ts +28 -13
  10. package/dist/src/app/agentApplication.js +93 -82
  11. package/dist/src/app/agentApplication.js.map +1 -1
  12. package/dist/src/app/agentApplicationBuilder.d.ts +2 -2
  13. package/dist/src/app/agentApplicationBuilder.js.map +1 -1
  14. package/dist/src/app/agentApplicationOptions.d.ts +9 -2
  15. package/dist/src/app/appRoute.d.ts +7 -0
  16. package/dist/src/app/{authorization.d.ts → auth/authorization.d.ts} +33 -139
  17. package/dist/src/app/auth/authorization.js +188 -0
  18. package/dist/src/app/auth/authorization.js.map +1 -0
  19. package/dist/src/app/auth/authorizationManager.d.ts +71 -0
  20. package/dist/src/app/auth/authorizationManager.js +170 -0
  21. package/dist/src/app/auth/authorizationManager.js.map +1 -0
  22. package/dist/src/app/auth/handlerStorage.d.ts +36 -0
  23. package/dist/src/app/auth/handlerStorage.js +62 -0
  24. package/dist/src/app/auth/handlerStorage.js.map +1 -0
  25. package/dist/src/app/auth/handlers/agenticAuthorization.d.ts +93 -0
  26. package/dist/src/app/auth/handlers/agenticAuthorization.js +134 -0
  27. package/dist/src/app/auth/handlers/agenticAuthorization.js.map +1 -0
  28. package/dist/src/app/auth/handlers/azureBotAuthorization.d.ts +222 -0
  29. package/dist/src/app/auth/handlers/azureBotAuthorization.js +428 -0
  30. package/dist/src/app/auth/handlers/azureBotAuthorization.js.map +1 -0
  31. package/dist/src/app/auth/handlers/index.d.ts +2 -0
  32. package/dist/src/app/auth/handlers/index.js +19 -0
  33. package/dist/src/app/auth/handlers/index.js.map +1 -0
  34. package/dist/src/app/auth/index.d.ts +2 -0
  35. package/dist/src/app/auth/index.js +19 -0
  36. package/dist/src/app/auth/index.js.map +1 -0
  37. package/dist/src/app/auth/types.d.ts +104 -0
  38. package/dist/src/app/auth/types.js +24 -0
  39. package/dist/src/app/auth/types.js.map +1 -0
  40. package/dist/src/app/index.d.ts +2 -3
  41. package/dist/src/app/index.js +2 -3
  42. package/dist/src/app/index.js.map +1 -1
  43. package/dist/src/app/routeList.d.ts +1 -1
  44. package/dist/src/app/routeList.js +22 -5
  45. package/dist/src/app/routeList.js.map +1 -1
  46. package/dist/src/app/streaming/streamingResponse.js +2 -1
  47. package/dist/src/app/streaming/streamingResponse.js.map +1 -1
  48. package/dist/src/auth/MemoryCache.d.ts +16 -0
  49. package/dist/src/auth/MemoryCache.js +58 -0
  50. package/dist/src/auth/MemoryCache.js.map +1 -0
  51. package/dist/src/auth/authConfiguration.d.ts +44 -2
  52. package/dist/src/auth/authConfiguration.js +209 -53
  53. package/dist/src/auth/authConfiguration.js.map +1 -1
  54. package/dist/src/auth/authConstants.d.ts +11 -0
  55. package/dist/src/auth/authConstants.js +15 -0
  56. package/dist/src/auth/authConstants.js.map +1 -0
  57. package/dist/src/auth/authProvider.d.ts +23 -0
  58. package/dist/src/auth/connections.d.ts +41 -0
  59. package/dist/src/auth/connections.js +7 -0
  60. package/dist/src/auth/connections.js.map +1 -0
  61. package/dist/src/auth/index.d.ts +2 -0
  62. package/dist/src/auth/index.js +2 -0
  63. package/dist/src/auth/index.js.map +1 -1
  64. package/dist/src/auth/jwt-middleware.js +31 -18
  65. package/dist/src/auth/jwt-middleware.js.map +1 -1
  66. package/dist/src/auth/msalConnectionManager.d.ts +64 -0
  67. package/dist/src/auth/msalConnectionManager.js +148 -0
  68. package/dist/src/auth/msalConnectionManager.js.map +1 -0
  69. package/dist/src/auth/msalTokenProvider.d.ts +31 -0
  70. package/dist/src/auth/msalTokenProvider.js +167 -16
  71. package/dist/src/auth/msalTokenProvider.js.map +1 -1
  72. package/dist/src/baseAdapter.d.ts +10 -25
  73. package/dist/src/baseAdapter.js +2 -15
  74. package/dist/src/baseAdapter.js.map +1 -1
  75. package/dist/src/cloudAdapter.d.ts +40 -23
  76. package/dist/src/cloudAdapter.js +128 -60
  77. package/dist/src/cloudAdapter.js.map +1 -1
  78. package/dist/src/connector-client/connectorClient.d.ts +15 -0
  79. package/dist/src/connector-client/connectorClient.js +49 -15
  80. package/dist/src/connector-client/connectorClient.js.map +1 -1
  81. package/dist/src/index.d.ts +0 -1
  82. package/dist/src/index.js +0 -1
  83. package/dist/src/index.js.map +1 -1
  84. package/dist/src/oauth/customUserTokenAPI.d.ts +1 -0
  85. package/dist/src/oauth/customUserTokenAPI.js +11 -0
  86. package/dist/src/oauth/customUserTokenAPI.js.map +1 -0
  87. package/dist/src/oauth/index.d.ts +0 -1
  88. package/dist/src/oauth/index.js +0 -1
  89. package/dist/src/oauth/index.js.map +1 -1
  90. package/dist/src/oauth/userTokenClient.d.ts +30 -13
  91. package/dist/src/oauth/userTokenClient.js +60 -26
  92. package/dist/src/oauth/userTokenClient.js.map +1 -1
  93. package/dist/src/oauth/userTokenClient.types.d.ts +19 -6
  94. package/dist/src/turnContext.d.ts +7 -1
  95. package/dist/src/turnContext.js +11 -4
  96. package/dist/src/turnContext.js.map +1 -1
  97. package/package.json +10 -6
  98. package/src/activityWireCompat.ts +12 -4
  99. package/src/agent-client/agentClient.ts +9 -3
  100. package/src/agent-client/agentResponseHandler.ts +5 -2
  101. package/src/app/agentApplication.ts +98 -77
  102. package/src/app/agentApplicationBuilder.ts +2 -2
  103. package/src/app/agentApplicationOptions.ts +10 -2
  104. package/src/app/appRoute.ts +8 -0
  105. package/src/app/auth/authorization.ts +252 -0
  106. package/src/app/auth/authorizationManager.ts +213 -0
  107. package/src/app/auth/handlerStorage.ts +61 -0
  108. package/src/app/auth/handlers/agenticAuthorization.ts +182 -0
  109. package/src/app/auth/handlers/azureBotAuthorization.ts +599 -0
  110. package/src/app/auth/handlers/index.ts +2 -0
  111. package/src/app/auth/index.ts +2 -0
  112. package/src/app/auth/types.ts +111 -0
  113. package/src/app/index.ts +2 -3
  114. package/src/app/routeList.ts +24 -5
  115. package/src/app/streaming/streamingResponse.ts +2 -1
  116. package/src/auth/MemoryCache.ts +59 -0
  117. package/src/auth/authConfiguration.ts +245 -52
  118. package/src/auth/authConstants.ts +11 -0
  119. package/src/auth/authProvider.ts +31 -0
  120. package/src/auth/connections.ts +47 -0
  121. package/src/auth/index.ts +2 -0
  122. package/src/auth/jwt-middleware.ts +38 -21
  123. package/src/auth/msalConnectionManager.ts +175 -0
  124. package/src/auth/msalTokenProvider.ts +209 -9
  125. package/src/baseAdapter.ts +10 -29
  126. package/src/cloudAdapter.ts +189 -71
  127. package/src/connector-client/connectorClient.ts +59 -15
  128. package/src/index.ts +0 -1
  129. package/src/oauth/customUserTokenAPI.ts +5 -0
  130. package/src/oauth/index.ts +0 -1
  131. package/src/oauth/userTokenClient.ts +74 -22
  132. package/src/oauth/userTokenClient.types.ts +20 -8
  133. package/src/turnContext.ts +16 -5
  134. package/dist/src/app/authorization.js +0 -387
  135. package/dist/src/app/authorization.js.map +0 -1
  136. package/dist/src/claimsIdentity.d.ts +0 -35
  137. package/dist/src/claimsIdentity.js +0 -43
  138. package/dist/src/claimsIdentity.js.map +0 -1
  139. package/dist/src/oauth/oAuthFlow.d.ts +0 -119
  140. package/dist/src/oauth/oAuthFlow.js +0 -316
  141. package/dist/src/oauth/oAuthFlow.js.map +0 -1
  142. package/src/app/authorization.ts +0 -432
  143. package/src/claimsIdentity.ts +0 -47
  144. package/src/oauth/oAuthFlow.ts +0 -378
@@ -1,378 +0,0 @@
1
- // Copyright (c) Microsoft Corporation. All rights reserved.
2
- // Licensed under the MIT License.
3
- import { debug } from '@microsoft/agents-activity/logger'
4
- import { Activity, ActivityTypes, Attachment } from '@microsoft/agents-activity'
5
- import {
6
- CardFactory,
7
- TurnContext,
8
- Storage,
9
- MessageFactory
10
- } from '../'
11
- import { UserTokenClient } from './userTokenClient'
12
- import { TokenExchangeRequest, TokenResponse } from './userTokenClient.types'
13
- import jwt, { JwtPayload } from 'jsonwebtoken'
14
-
15
- const logger = debug('agents:oauth-flow')
16
-
17
- /**
18
- * Represents the state of the OAuth flow.
19
- * @interface FlowState
20
- */
21
- export interface FlowState {
22
- /** Indicates whether the OAuth flow has been started */
23
- flowStarted: boolean | undefined,
24
- /** Timestamp when the OAuth flow expires (in milliseconds since epoch) */
25
- flowExpires: number | undefined,
26
- /** The absolute OAuth connection name used for the flow, null if not set */
27
- absOauthConnectionName: string
28
- /** Optional activity to continue the flow with, used for multi-turn scenarios */
29
- continuationActivity?: Activity | null
30
-
31
- eTag?: string // Optional ETag for optimistic concurrency control
32
- }
33
-
34
- interface TokenVerifyState {
35
- state: string
36
- }
37
-
38
- interface CachedToken {
39
- token: TokenResponse
40
- expiresAt: number
41
- }
42
-
43
- /**
44
- * Manages the OAuth flow
45
- */
46
- export class OAuthFlow {
47
- /**
48
- * The user token client used for managing user tokens.
49
- */
50
- userTokenClient: UserTokenClient
51
-
52
- /**
53
- * The current state of the OAuth flow.
54
- */
55
- state: FlowState
56
-
57
- /**
58
- * The ID of the token exchange request, used to deduplicate requests.
59
- */
60
- tokenExchangeId: string | null = null
61
-
62
- /**
63
- * In-memory cache for tokens with expiration.
64
- */
65
- private tokenCache: Map<string, CachedToken> = new Map()
66
-
67
- /**
68
- * The name of the OAuth connection.
69
- */
70
- absOauthConnectionName: string
71
-
72
- /**
73
- * The title of the OAuth card.
74
- */
75
- cardTitle: string = 'Sign in'
76
-
77
- /**
78
- * The text of the OAuth card.
79
- */
80
- cardText: string = 'login'
81
-
82
- /**
83
- * Creates a new instance of OAuthFlow.
84
- * @param storage The storage provider for persisting flow state.
85
- * @param absOauthConnectionName The absolute OAuth connection name.
86
- * @param tokenClient Optional user token client. If not provided, will be initialized automatically.
87
- * @param cardTitle Optional title for the OAuth card. Defaults to 'Sign in'.
88
- * @param cardText Optional text for the OAuth card. Defaults to 'login'.
89
- */
90
- constructor (private storage: Storage, absOauthConnectionName: string, tokenClient: UserTokenClient, cardTitle?: string, cardText?: string) {
91
- this.state = { flowStarted: undefined, flowExpires: undefined, absOauthConnectionName }
92
- this.absOauthConnectionName = absOauthConnectionName
93
- this.userTokenClient = tokenClient
94
- this.cardTitle = cardTitle ?? this.cardTitle
95
- this.cardText = cardText ?? this.cardText
96
- }
97
-
98
- /**
99
- * Retrieves the user token from the user token service with in-memory caching for 10 minutes.
100
- * @param context The turn context containing the activity information.
101
- * @returns A promise that resolves to the user token response.
102
- * @throws Will throw an error if the channelId or from properties are not set in the activity.
103
- */
104
- public async getUserToken (context: TurnContext): Promise<TokenResponse> {
105
- const activity = context.activity
106
-
107
- if (!activity.channelId || !activity.from || !activity.from.id) {
108
- throw new Error('UserTokenService requires channelId and from to be set')
109
- }
110
-
111
- const cacheKey = this.getCacheKey(context)
112
-
113
- const cachedEntry = this.tokenCache.get(cacheKey)
114
- if (cachedEntry && Date.now() < cachedEntry.expiresAt) {
115
- logger.info(`Returning cached token for user with cache key: ${cacheKey}`)
116
- return cachedEntry.token
117
- }
118
-
119
- logger.info('Get token from user token service')
120
- await this.refreshToken(context)
121
- const tokenResponse = await this.userTokenClient.getUserToken(this.absOauthConnectionName, activity.channelId, activity.from.id)
122
-
123
- // Cache the token if it's valid (has a token value)
124
- if (tokenResponse && tokenResponse.token) {
125
- const cacheExpiry = Date.now() + (10 * 60 * 1000) // 10 minutes from now
126
- this.tokenCache.set(cacheKey, {
127
- token: tokenResponse,
128
- expiresAt: cacheExpiry
129
- })
130
- logger.info('Token cached for 10 minutes')
131
- }
132
-
133
- return tokenResponse
134
- }
135
-
136
- /**
137
- * Begins the OAuth flow.
138
- * @param context The turn context.
139
- * @returns A promise that resolves to the user token if available, or undefined if OAuth flow needs to be started.
140
- */
141
- public async beginFlow (context: TurnContext): Promise<TokenResponse | undefined> {
142
- this.state = await this.getFlowState(context)
143
- if (this.absOauthConnectionName === '') {
144
- throw new Error('connectionName is not set')
145
- }
146
- logger.info('Starting OAuth flow for connectionName:', this.absOauthConnectionName)
147
- await this.refreshToken(context)
148
-
149
- const act = context.activity
150
-
151
- // Check cache first before starting OAuth flow
152
- if (act.channelId && act.from && act.from.id) {
153
- const cacheKey = this.getCacheKey(context)
154
- const cachedEntry = this.tokenCache.get(cacheKey)
155
- if (cachedEntry && Date.now() < cachedEntry.expiresAt) {
156
- logger.info(`Returning cached token for user in beginFlow with cache key: ${cacheKey}`)
157
- return cachedEntry.token
158
- }
159
- }
160
-
161
- const output = await this.userTokenClient.getTokenOrSignInResource(act.from?.id!, this.absOauthConnectionName, act.channelId!, act.getConversationReference(), act.relatesTo!, undefined!)
162
- if (output && output.tokenResponse) {
163
- // Cache the token if it's valid
164
- if (act.channelId && act.from && act.from.id) {
165
- const cacheKey = this.getCacheKey(context)
166
- const cacheExpiry = Date.now() + (10 * 60 * 1000) // 10 minutes from now
167
- this.tokenCache.set(cacheKey, {
168
- token: output.tokenResponse,
169
- expiresAt: cacheExpiry
170
- })
171
- logger.info('Token cached for 10 minutes in beginFlow')
172
- this.state = { flowStarted: false, flowExpires: 0, absOauthConnectionName: this.absOauthConnectionName }
173
- }
174
- logger.info('Token retrieved successfully')
175
- return output.tokenResponse
176
- }
177
- const oCard: Attachment = CardFactory.oauthCard(this.absOauthConnectionName, this.cardTitle, this.cardText, output.signInResource)
178
- await context.sendActivity(MessageFactory.attachment(oCard))
179
- this.state = { flowStarted: true, flowExpires: Date.now() + 60 * 5 * 1000, absOauthConnectionName: this.absOauthConnectionName }
180
- await this.storage.write({ [this.getFlowStateKey(context)]: this.state })
181
- logger.info('OAuth card sent, flow started')
182
- return undefined
183
- }
184
-
185
- /**
186
- * Continues the OAuth flow.
187
- * @param context The turn context.
188
- * @returns A promise that resolves to the user token response.
189
- */
190
- public async continueFlow (context: TurnContext): Promise<TokenResponse> {
191
- this.state = await this.getFlowState(context)
192
- await this.refreshToken(context)
193
- if (this.state?.flowExpires !== 0 && Date.now() > this.state?.flowExpires!) {
194
- logger.warn('Flow expired')
195
- await context.sendActivity(MessageFactory.text('Sign-in session expired. Please try again.'))
196
- this.state!.flowStarted = false
197
- return { token: undefined }
198
- }
199
- const contFlowActivity = context.activity
200
- if (contFlowActivity.type === ActivityTypes.Message) {
201
- const magicCode = contFlowActivity.text as string
202
- if (magicCode.match(/^\d{6}$/)) {
203
- const result = await this.userTokenClient?.getUserToken(this.absOauthConnectionName, contFlowActivity.channelId!, contFlowActivity.from?.id!, magicCode)!
204
- if (result && result.token) {
205
- // Cache the token if it's valid
206
- if (contFlowActivity.channelId && contFlowActivity.from && contFlowActivity.from.id) {
207
- const cacheKey = this.getCacheKey(context)
208
- const cacheExpiry = Date.now() + (10 * 60 * 1000) // 10 minutes from now
209
- this.tokenCache.set(cacheKey, {
210
- token: result,
211
- expiresAt: cacheExpiry
212
- })
213
- logger.info('Token cached for 10 minutes in continueFlow (magic code)')
214
- }
215
-
216
- await this.storage.delete([this.getFlowStateKey(context)])
217
- logger.info('Token retrieved successfully')
218
- return result
219
- } else {
220
- // await context.sendActivity(MessageFactory.text('Invalid code. Please try again.'))
221
- logger.warn('Invalid magic code provided')
222
- this.state = { flowStarted: true, flowExpires: Date.now() + 30000, absOauthConnectionName: this.absOauthConnectionName }
223
- await this.storage.write({ [this.getFlowStateKey(context)]: this.state })
224
- return { token: undefined }
225
- }
226
- } else {
227
- logger.warn('Invalid magic code format')
228
- await context.sendActivity(MessageFactory.text('Invalid code format. Please enter a 6-digit code.'))
229
- return { token: undefined }
230
- }
231
- }
232
-
233
- if (contFlowActivity.type === ActivityTypes.Invoke && contFlowActivity.name === 'signin/verifyState') {
234
- logger.info('Continuing OAuth flow with verifyState')
235
- const tokenVerifyState = contFlowActivity.value as TokenVerifyState
236
- const magicCode = tokenVerifyState.state
237
- const result = await this.userTokenClient?.getUserToken(this.absOauthConnectionName, contFlowActivity.channelId!, contFlowActivity.from?.id!, magicCode)!
238
- // Cache the token if it's valid
239
- if (result && result.token && contFlowActivity.channelId && contFlowActivity.from && contFlowActivity.from.id) {
240
- const cacheKey = this.getCacheKey(context)
241
- const cacheExpiry = Date.now() + (10 * 60 * 1000) // 10 minutes from now
242
- this.tokenCache.set(cacheKey, {
243
- token: result,
244
- expiresAt: cacheExpiry
245
- })
246
- logger.info('Token cached for 10 minutes in continueFlow (verifyState)')
247
- }
248
- return result
249
- }
250
-
251
- if (contFlowActivity.type === ActivityTypes.Invoke && contFlowActivity.name === 'signin/tokenExchange') {
252
- logger.info('Continuing OAuth flow with tokenExchange')
253
- const tokenExchangeRequest = contFlowActivity.value as TokenExchangeRequest
254
- if (this.tokenExchangeId === tokenExchangeRequest.id) { // dedupe
255
- logger.debug('Token exchange request already processed, skipping')
256
- return { token: undefined }
257
- }
258
- this.tokenExchangeId = tokenExchangeRequest.id!
259
- const userTokenResp = await this.userTokenClient?.exchangeTokenAsync(contFlowActivity.from?.id!, this.absOauthConnectionName, contFlowActivity.channelId!, tokenExchangeRequest)
260
- if (userTokenResp && userTokenResp.token) {
261
- // Cache the token if it's valid
262
- if (contFlowActivity.channelId && contFlowActivity.from && contFlowActivity.from.id) {
263
- const cacheKey = this.getCacheKey(context)
264
- const cacheExpiry = Date.now() + (10 * 60 * 1000) // 10 minutes from now
265
- this.tokenCache.set(cacheKey, {
266
- token: userTokenResp,
267
- expiresAt: cacheExpiry
268
- })
269
- logger.info('Token cached for 10 minutes in continueFlow (tokenExchange)')
270
- }
271
-
272
- logger.info('Token exchanged')
273
- this.state!.flowStarted = false
274
- await this.storage.write({ [this.getFlowStateKey(context)]: this.state })
275
- return userTokenResp
276
- } else {
277
- logger.warn('Token exchange failed')
278
- this.state!.flowStarted = true
279
- return { token: undefined }
280
- }
281
- }
282
- return { token: undefined }
283
- }
284
-
285
- /**
286
- * Signs the user out.
287
- * @param context The turn context.
288
- * @returns A promise that resolves when the sign-out operation is complete.
289
- */
290
- public async signOut (context: TurnContext): Promise<void> {
291
- await this.refreshToken(context)
292
-
293
- // Clear cached token for this user
294
- const activity = context.activity
295
- if (activity.channelId && activity.from && activity.from.id) {
296
- const cacheKey = this.getCacheKey(context)
297
- this.tokenCache.delete(cacheKey)
298
- logger.info('Cached token cleared for user')
299
- }
300
-
301
- await this.userTokenClient?.signOut(context.activity.from?.id as string, this.absOauthConnectionName, context.activity.channelId as string)
302
- this.state = { flowStarted: false, flowExpires: 0, absOauthConnectionName: this.absOauthConnectionName }
303
- await this.storage.delete([this.getFlowStateKey(context)])
304
- logger.info('User signed out successfully from connection:', this.absOauthConnectionName)
305
- }
306
-
307
- /**
308
- * Gets the user state for the OAuth flow.
309
- * @param context The turn context.
310
- * @returns A promise that resolves to the flow state.
311
- */
312
- public async getFlowState (context: TurnContext) : Promise<FlowState> {
313
- const key = this.getFlowStateKey(context)
314
- const data = await this.storage.read([key])
315
- const flowState: FlowState = data[key] // ?? { flowStarted: false, flowExpires: 0 }
316
- return flowState
317
- }
318
-
319
- /**
320
- * Sets the flow state for the OAuth flow.
321
- * @param context The turn context.
322
- * @param flowState The flow state to set.
323
- * @returns A promise that resolves when the flow state is set.
324
- */
325
- public async setFlowState (context: TurnContext, flowState: FlowState) : Promise<void> {
326
- const key = this.getFlowStateKey(context)
327
- await this.storage.write({ [key]: flowState })
328
- this.state = flowState
329
- logger.debug(`Flow state set: ${JSON.stringify(flowState)}`)
330
- }
331
-
332
- /**
333
- * Initializes the user token client if not already initialized.
334
- * @param context The turn context used to get authentication credentials.
335
- */
336
- private async refreshToken (context: TurnContext) {
337
- const cachedToken = this.tokenCache.get('__access_token__')
338
- if (!cachedToken || Date.now() > cachedToken.expiresAt) {
339
- const accessToken = await context.adapter.authProvider.getAccessToken(context.adapter.authConfig, 'https://api.botframework.com')
340
- const decodedToken = jwt.decode(accessToken) as JwtPayload
341
- this.tokenCache.set('__access_token__', {
342
- token: { token: accessToken },
343
- expiresAt: decodedToken?.exp ? decodedToken.exp * 1000 - 1000 : Date.now() + 10 * 60 * 1000
344
- })
345
- this.userTokenClient.updateAuthToken(accessToken)
346
- }
347
- }
348
-
349
- /**
350
- * Generates a cache key for storing user tokens.
351
- * @param context The turn context containing activity information.
352
- * @returns The cache key string in format: channelId_userId_connectionName.
353
- * @throws Will throw an error if required activity properties are missing.
354
- */
355
- private getCacheKey (context: TurnContext): string {
356
- const activity = context.activity
357
- if (!activity.channelId || !activity.from || !activity.from.id) {
358
- throw new Error('ChannelId and from.id must be set in the activity for cache key generation')
359
- }
360
- return `${activity.channelId}_${activity.from.id}_${this.absOauthConnectionName}`
361
- }
362
-
363
- /**
364
- * Generates a storage key for persisting OAuth flow state.
365
- * @param context The turn context containing activity information.
366
- * @returns The storage key string in format: oauth/channelId/conversationId/userId/flowState.
367
- * @throws Will throw an error if required activity properties are missing.
368
- */
369
- private getFlowStateKey (context: TurnContext): string {
370
- const channelId = context.activity.channelId
371
- const conversationId = context.activity.conversation?.id
372
- const userId = context.activity.from?.id
373
- if (!channelId || !conversationId || !userId) {
374
- throw new Error('ChannelId, conversationId, and userId must be set in the activity')
375
- }
376
- return `oauth/${channelId}/${userId}/${this.absOauthConnectionName}/flowState`
377
- }
378
- }