@kya-os/mcp-i-core 1.7.0 → 1.8.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 (121) hide show
  1. package/README.md +1 -1
  2. package/dist/conformance/capability-verifier-adapter.d.ts +66 -0
  3. package/dist/conformance/capability-verifier-adapter.js +61 -0
  4. package/dist/conformance/index.d.ts +10 -0
  5. package/dist/conformance/index.js +19 -0
  6. package/dist/conformance/validate-level2.d.ts +203 -0
  7. package/dist/conformance/validate-level2.js +294 -0
  8. package/dist/conformance/vc-jwt-verifier.d.ts +55 -0
  9. package/dist/conformance/vc-jwt-verifier.js +147 -0
  10. package/dist/delegation/did-web-resolver.d.ts +60 -0
  11. package/dist/delegation/did-web-resolver.js +129 -0
  12. package/dist/delegation/outbound-proof.d.ts +3 -2
  13. package/dist/delegation/outbound-proof.js +3 -2
  14. package/dist/delegation/utils.d.ts +3 -1
  15. package/dist/index.d.ts +9 -63
  16. package/dist/index.js +22 -161
  17. package/dist/utils/base58.d.ts +4 -28
  18. package/dist/utils/base58.js +18 -98
  19. package/dist/utils/base64.d.ts +4 -29
  20. package/dist/utils/base64.js +18 -167
  21. package/dist/utils/did-helpers.d.ts +4 -165
  22. package/dist/utils/did-helpers.js +18 -217
  23. package/package.json +5 -7
  24. package/dist/auth/handshake.d.ts +0 -119
  25. package/dist/auth/handshake.js +0 -250
  26. package/dist/auth/index.d.ts +0 -6
  27. package/dist/auth/index.js +0 -11
  28. package/dist/auth/types.d.ts +0 -46
  29. package/dist/auth/types.js +0 -10
  30. package/dist/cache/oauth-config-cache.d.ts +0 -69
  31. package/dist/cache/oauth-config-cache.js +0 -76
  32. package/dist/cache/tool-protection-cache.d.ts +0 -89
  33. package/dist/cache/tool-protection-cache.js +0 -118
  34. package/dist/compliance/index.d.ts +0 -8
  35. package/dist/compliance/index.js +0 -24
  36. package/dist/compliance/schema-registry.d.ts +0 -50
  37. package/dist/compliance/schema-registry.js +0 -438
  38. package/dist/compliance/schema-verifier.d.ts +0 -110
  39. package/dist/compliance/schema-verifier.js +0 -518
  40. package/dist/config/remote-config.d.ts +0 -173
  41. package/dist/config/remote-config.js +0 -253
  42. package/dist/config.d.ts +0 -182
  43. package/dist/config.js +0 -148
  44. package/dist/identity/idp-token-resolver.d.ts +0 -69
  45. package/dist/identity/idp-token-resolver.js +0 -136
  46. package/dist/identity/idp-token-storage.interface.d.ts +0 -80
  47. package/dist/identity/idp-token-storage.interface.js +0 -14
  48. package/dist/identity/user-did-manager.d.ts +0 -228
  49. package/dist/identity/user-did-manager.js +0 -356
  50. package/dist/logging/index.d.ts +0 -5
  51. package/dist/logging/index.js +0 -10
  52. package/dist/logging/logger.d.ts +0 -33
  53. package/dist/logging/logger.js +0 -104
  54. package/dist/proof/generator.d.ts +0 -109
  55. package/dist/proof/generator.js +0 -236
  56. package/dist/proof/index.d.ts +0 -5
  57. package/dist/proof/index.js +0 -11
  58. package/dist/providers/base.d.ts +0 -95
  59. package/dist/providers/base.js +0 -47
  60. package/dist/providers/memory.d.ts +0 -42
  61. package/dist/providers/memory.js +0 -121
  62. package/dist/runtime/audit-logger.d.ts +0 -37
  63. package/dist/runtime/audit-logger.js +0 -9
  64. package/dist/runtime/base.d.ts +0 -375
  65. package/dist/runtime/base.js +0 -1491
  66. package/dist/runtime/ext-apps-constants.d.ts +0 -14
  67. package/dist/runtime/ext-apps-constants.js +0 -17
  68. package/dist/services/access-control.service.d.ts +0 -138
  69. package/dist/services/access-control.service.js +0 -721
  70. package/dist/services/authorization/authorization-registry.d.ts +0 -29
  71. package/dist/services/authorization/authorization-registry.js +0 -58
  72. package/dist/services/authorization/types.d.ts +0 -53
  73. package/dist/services/authorization/types.js +0 -10
  74. package/dist/services/batch-delegation.service.d.ts +0 -53
  75. package/dist/services/batch-delegation.service.js +0 -95
  76. package/dist/services/crypto.service.d.ts +0 -69
  77. package/dist/services/crypto.service.js +0 -225
  78. package/dist/services/delegation-error-formatter.d.ts +0 -124
  79. package/dist/services/delegation-error-formatter.js +0 -214
  80. package/dist/services/errors.d.ts +0 -49
  81. package/dist/services/errors.js +0 -66
  82. package/dist/services/index.d.ts +0 -9
  83. package/dist/services/index.js +0 -15
  84. package/dist/services/oauth-config.service.d.ts +0 -53
  85. package/dist/services/oauth-config.service.js +0 -141
  86. package/dist/services/oauth-provider-registry.d.ts +0 -88
  87. package/dist/services/oauth-provider-registry.js +0 -128
  88. package/dist/services/oauth-service.d.ts +0 -122
  89. package/dist/services/oauth-service.js +0 -442
  90. package/dist/services/oauth-token-retrieval.service.d.ts +0 -49
  91. package/dist/services/oauth-token-retrieval.service.js +0 -150
  92. package/dist/services/policy.service.d.ts +0 -130
  93. package/dist/services/policy.service.js +0 -399
  94. package/dist/services/proof-verifier.d.ts +0 -98
  95. package/dist/services/proof-verifier.js +0 -319
  96. package/dist/services/provider-resolver.d.ts +0 -89
  97. package/dist/services/provider-resolver.js +0 -196
  98. package/dist/services/provider-validator.d.ts +0 -55
  99. package/dist/services/provider-validator.js +0 -135
  100. package/dist/services/session-registration.service.d.ts +0 -80
  101. package/dist/services/session-registration.service.js +0 -174
  102. package/dist/services/storage.service.d.ts +0 -116
  103. package/dist/services/storage.service.js +0 -411
  104. package/dist/services/tool-context-builder.d.ts +0 -74
  105. package/dist/services/tool-context-builder.js +0 -215
  106. package/dist/services/tool-protection.service.d.ts +0 -193
  107. package/dist/services/tool-protection.service.js +0 -736
  108. package/dist/session/index.d.ts +0 -5
  109. package/dist/session/index.js +0 -11
  110. package/dist/session/manager.d.ts +0 -113
  111. package/dist/session/manager.js +0 -273
  112. package/dist/types/oauth-required-error.d.ts +0 -46
  113. package/dist/types/oauth-required-error.js +0 -42
  114. package/dist/types/tool-protection.d.ts +0 -144
  115. package/dist/types/tool-protection.js +0 -48
  116. package/dist/utils/cors.d.ts +0 -44
  117. package/dist/utils/cors.js +0 -71
  118. package/dist/utils/index.d.ts +0 -8
  119. package/dist/utils/index.js +0 -24
  120. package/dist/utils/storage-keys.d.ts +0 -120
  121. package/dist/utils/storage-keys.js +0 -217
@@ -1,442 +0,0 @@
1
- "use strict";
2
- /**
3
- * OAuth Service
4
- *
5
- * Handles OAuth token exchange and refresh using PKCE (Proof Key for Code Exchange).
6
- * Supports both direct PKCE exchange with OAuth providers and proxy mode via AgentShield.
7
- *
8
- * MCP-I Provider Registry Model:
9
- * - Client secrets are NOT sent via the API response
10
- * - Agents receive metadata.clientSecretName from AgentShield
11
- * - Secrets are resolved at runtime from secure storage (Cloudflare Worker env)
12
- * - The SecretResolver interface enables platform-specific secret resolution
13
- *
14
- * @package @kya-os/mcp-i-core
15
- */
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.OAuthService = exports.defaultSecretResolver = void 0;
18
- /**
19
- * Default secret resolver that uses environment variables
20
- * Used when no custom resolver is provided
21
- */
22
- exports.defaultSecretResolver = {
23
- async resolveSecret(secretName) {
24
- // For Node.js environments, check process.env
25
- if (typeof process !== "undefined" && process.env) {
26
- return process.env[secretName];
27
- }
28
- return undefined;
29
- },
30
- };
31
- /**
32
- * Service for OAuth token exchange and refresh
33
- */
34
- class OAuthService {
35
- config;
36
- constructor(config) {
37
- this.config = {
38
- configService: config.configService,
39
- fetchProvider: config.fetchProvider,
40
- agentShieldApiUrl: config.agentShieldApiUrl,
41
- agentShieldApiKey: config.agentShieldApiKey,
42
- projectId: config.projectId,
43
- logger: config.logger || (() => { }),
44
- secretResolver: config.secretResolver || exports.defaultSecretResolver,
45
- };
46
- }
47
- /**
48
- * Resolve client secret for a provider using the MCP-I provider-registry model
49
- *
50
- * Resolution order:
51
- * 1. If metadata.clientSecretName exists, resolve from secure storage
52
- * 2. Fall back to clientSecret field (legacy/backward compatibility)
53
- *
54
- * @param providerConfig - The OAuth provider configuration
55
- * @returns The resolved client secret, or undefined if not available
56
- */
57
- async resolveClientSecret(providerConfig) {
58
- // MCP-I Provider Registry model: resolve secret by name
59
- if (providerConfig.metadata?.clientSecretName) {
60
- const secretName = providerConfig.metadata.clientSecretName;
61
- this.config.logger("[OAuthService] Resolving client secret by name", {
62
- secretName,
63
- version: providerConfig.metadata.clientSecretVersion,
64
- });
65
- const secret = await this.config.secretResolver.resolveSecret(secretName);
66
- if (secret) {
67
- this.config.logger("[OAuthService] Client secret resolved successfully", {
68
- secretName,
69
- });
70
- return secret;
71
- }
72
- this.config.logger("[OAuthService] Client secret not found in secure storage", {
73
- secretName,
74
- });
75
- // Fall through to try clientSecret field
76
- }
77
- // Legacy model: use clientSecret directly (if provided)
78
- // DEPRECATED: This path is for backward compatibility only
79
- // New deployments should use metadata.clientSecretName with secure storage
80
- if (providerConfig.clientSecret) {
81
- this.config.logger("[OAuthService] DEPRECATED: Using legacy clientSecret field - " +
82
- "migrate to metadata.clientSecretName for better security", {
83
- telemetry: {
84
- event: "oauth.deprecated_client_secret_used",
85
- hasMetadata: !!providerConfig.metadata,
86
- hasSecretName: !!providerConfig.metadata?.clientSecretName,
87
- },
88
- });
89
- return providerConfig.clientSecret;
90
- }
91
- return undefined;
92
- }
93
- /**
94
- * Exchange authorization code for IDP tokens using PKCE
95
- *
96
- * For PKCE providers: Exchanges code directly with OAuth provider (no client secret)
97
- * For proxy mode: Exchanges code via AgentShield API
98
- *
99
- * @param provider - OAuth provider name (e.g., "github", "google")
100
- * @param code - Authorization code from OAuth callback
101
- * @param codeVerifier - PKCE code verifier (optional for non-PKCE providers in proxy mode)
102
- * @param redirectUri - Redirect URI used in authorization request
103
- * @returns IDP tokens (access_token, refresh_token, expires_at, etc.)
104
- */
105
- async exchangeToken(provider, code, codeVerifier, redirectUri) {
106
- // Fetch provider config
107
- const oauthConfig = await this.config.configService.getOAuthConfig(this.config.projectId);
108
- const providerConfig = oauthConfig.providers[provider];
109
- if (!providerConfig) {
110
- throw new Error(`Provider "${provider}" not configured for project "${this.config.projectId}"`);
111
- }
112
- // For PKCE providers, require codeVerifier
113
- if (providerConfig.supportsPKCE && !providerConfig.proxyMode) {
114
- if (!codeVerifier) {
115
- throw new Error(`Provider "${provider}" requires PKCE code_verifier for token exchange`);
116
- }
117
- return this.exchangeTokenPKCE(providerConfig, code, codeVerifier, redirectUri || "");
118
- }
119
- // For proxy mode, codeVerifier is optional (only included if PKCE is supported)
120
- if (providerConfig.proxyMode) {
121
- return this.exchangeTokenProxy(providerConfig, code, codeVerifier, redirectUri || "");
122
- }
123
- throw new Error(`Provider "${provider}" configuration is invalid: must support PKCE or use proxy mode`);
124
- }
125
- /**
126
- * Exchange token directly with OAuth provider using PKCE
127
- */
128
- async exchangeTokenPKCE(providerConfig, code, codeVerifier, redirectUri) {
129
- // Resolve client secret using MCP-I provider-registry model
130
- const clientSecret = await this.resolveClientSecret(providerConfig);
131
- this.config.logger("[OAuthService] Exchanging token with PKCE", {
132
- provider: providerConfig.authorizationUrl,
133
- tokenUrl: providerConfig.tokenUrl,
134
- hasClientSecret: !!clientSecret,
135
- resolvedViaSecretName: !!providerConfig.metadata?.clientSecretName,
136
- });
137
- // Build token exchange parameters
138
- // Note: GitHub OAuth Apps require client_secret even with PKCE
139
- // (GitHub Apps can use PKCE without client_secret, but OAuth Apps cannot)
140
- const params = {
141
- grant_type: "authorization_code",
142
- code,
143
- redirect_uri: redirectUri,
144
- client_id: providerConfig.clientId,
145
- code_verifier: codeVerifier,
146
- };
147
- // Include client_secret if resolved (either from secure storage or legacy field)
148
- // This is required for GitHub OAuth Apps and other providers that need it
149
- if (clientSecret) {
150
- params.client_secret = clientSecret;
151
- }
152
- const response = await this.config.fetchProvider.fetch(providerConfig.tokenUrl, {
153
- method: "POST",
154
- headers: {
155
- "Content-Type": "application/x-www-form-urlencoded",
156
- Accept: "application/json",
157
- },
158
- body: new URLSearchParams(params).toString(),
159
- });
160
- if (!response.ok) {
161
- const errorText = await response.text().catch(() => "Unknown error");
162
- let errorData;
163
- try {
164
- errorData = JSON.parse(errorText);
165
- }
166
- catch {
167
- errorData = { error: errorText };
168
- }
169
- const errorMessage = errorData.error_description || errorData.error || errorText;
170
- this.config.logger("[OAuthService] Token exchange failed", {
171
- status: response.status,
172
- error: errorMessage,
173
- provider: providerConfig.tokenUrl,
174
- });
175
- throw new Error(`Token exchange failed: ${errorMessage} (${response.status})`);
176
- }
177
- const tokens = await response.json();
178
- // GitHub returns errors with 200 status - check for error field first
179
- if (tokens.error) {
180
- this.config.logger("[OAuthService] Token exchange returned error (200 status)", {
181
- error: tokens.error,
182
- errorDescription: tokens.error_description,
183
- errorUri: tokens.error_uri,
184
- provider: providerConfig.tokenUrl,
185
- responseKeys: Object.keys(tokens),
186
- });
187
- throw new Error(`Token exchange failed: ${tokens.error_description || tokens.error}`);
188
- }
189
- // Validate required fields
190
- if (!tokens.access_token) {
191
- this.config.logger("[OAuthService] Token response missing access_token", {
192
- responseKeys: Object.keys(tokens),
193
- provider: providerConfig.tokenUrl,
194
- });
195
- throw new Error("Token response missing access_token");
196
- }
197
- // Calculate expiration timestamp
198
- const expiresIn = tokens.expires_in || 3600; // Default 1 hour
199
- const expiresAt = Date.now() + expiresIn * 1000;
200
- const idpTokens = {
201
- access_token: tokens.access_token,
202
- refresh_token: tokens.refresh_token,
203
- expires_in: expiresIn,
204
- expires_at: expiresAt,
205
- token_type: tokens.token_type || "Bearer",
206
- scope: tokens.scope,
207
- };
208
- this.config.logger("[OAuthService] Token exchange successful", {
209
- provider: providerConfig.tokenUrl,
210
- expiresAt: new Date(expiresAt).toISOString(),
211
- hasRefreshToken: !!idpTokens.refresh_token,
212
- });
213
- return idpTokens;
214
- }
215
- /**
216
- * Exchange token via AgentShield proxy (for providers that require proxy mode)
217
- *
218
- * Note: For Phase 3 two-step flow, OAuth tokens are retrieved separately via
219
- * OAuthTokenRetrievalService in the callback handler. This method maintains
220
- * backward compatibility for direct proxy mode usage.
221
- */
222
- async exchangeTokenProxy(providerConfig, code, codeVerifier, redirectUri) {
223
- // Exchange via AgentShield proxy endpoint
224
- const proxyUrl = `${this.config.agentShieldApiUrl}/api/v1/oauth/token`;
225
- this.config.logger("[OAuthService] Exchanging token via proxy", {
226
- proxyUrl,
227
- provider: providerConfig.authorizationUrl,
228
- hasCodeVerifier: !!codeVerifier,
229
- supportsPKCE: providerConfig.supportsPKCE,
230
- });
231
- // Build request body - only include code_verifier if PKCE is supported and provided
232
- const requestBody = {
233
- grant_type: "authorization_code",
234
- code,
235
- redirect_uri: redirectUri || "",
236
- provider: providerConfig.authorizationUrl,
237
- project_id: this.config.projectId,
238
- };
239
- // Include code_verifier only if provider supports PKCE and verifier is provided
240
- if (providerConfig.supportsPKCE && codeVerifier) {
241
- requestBody.code_verifier = codeVerifier;
242
- }
243
- const response = await this.config.fetchProvider.fetch(proxyUrl, {
244
- method: "POST",
245
- headers: {
246
- "Content-Type": "application/json",
247
- Authorization: `Bearer ${this.config.agentShieldApiKey}`,
248
- },
249
- body: JSON.stringify(requestBody),
250
- });
251
- if (!response.ok) {
252
- const errorText = await response.text().catch(() => "Unknown error");
253
- let errorData;
254
- try {
255
- errorData = JSON.parse(errorText);
256
- }
257
- catch {
258
- errorData = { error: errorText };
259
- }
260
- const errorMessage = errorData.error_description || errorData.error || errorText;
261
- this.config.logger("[OAuthService] Proxy token exchange failed", {
262
- status: response.status,
263
- error: errorMessage,
264
- proxyUrl,
265
- });
266
- throw new Error(`Proxy token exchange failed: ${errorMessage} (${response.status})`);
267
- }
268
- const result = await response.json();
269
- const tokens = result.data || result;
270
- // Validate required fields
271
- if (!tokens.access_token) {
272
- throw new Error("Proxy token response missing access_token");
273
- }
274
- // Calculate expiration timestamp
275
- const expiresIn = tokens.expires_in || 3600; // Default 1 hour
276
- const expiresAt = Date.now() + expiresIn * 1000;
277
- const idpTokens = {
278
- access_token: tokens.access_token,
279
- refresh_token: tokens.refresh_token,
280
- expires_in: expiresIn,
281
- expires_at: expiresAt,
282
- token_type: tokens.token_type || "Bearer",
283
- scope: tokens.scope,
284
- };
285
- this.config.logger("[OAuthService] Proxy token exchange successful", {
286
- proxyUrl,
287
- expiresAt: new Date(expiresAt).toISOString(),
288
- hasRefreshToken: !!idpTokens.refresh_token,
289
- });
290
- return idpTokens;
291
- }
292
- /**
293
- * Refresh IDP access token using refresh token
294
- *
295
- * For PKCE providers: Refreshes directly with OAuth provider
296
- * For proxy mode: Refreshes via AgentShield API
297
- *
298
- * @param provider - OAuth provider name
299
- * @param refreshToken - Refresh token from previous token exchange
300
- * @returns New IDP tokens or null if refresh failed
301
- */
302
- async refreshToken(provider, refreshToken) {
303
- // Fetch provider config
304
- const oauthConfig = await this.config.configService.getOAuthConfig(this.config.projectId);
305
- const providerConfig = oauthConfig.providers[provider];
306
- if (!providerConfig) {
307
- this.config.logger("[OAuthService] Provider not found for refresh", {
308
- provider,
309
- });
310
- return null;
311
- }
312
- // For PKCE providers, refresh directly with OAuth provider
313
- if (providerConfig.supportsPKCE && !providerConfig.proxyMode) {
314
- return this.refreshTokenPKCE(providerConfig, refreshToken);
315
- }
316
- // For proxy mode, refresh via AgentShield
317
- if (providerConfig.proxyMode) {
318
- return this.refreshTokenProxy(providerConfig, refreshToken);
319
- }
320
- return null;
321
- }
322
- /**
323
- * Refresh token directly with OAuth provider using PKCE
324
- */
325
- async refreshTokenPKCE(providerConfig, refreshToken) {
326
- this.config.logger("[OAuthService] Refreshing token with PKCE", {
327
- provider: providerConfig.tokenUrl,
328
- });
329
- try {
330
- const response = await this.config.fetchProvider.fetch(providerConfig.tokenUrl, {
331
- method: "POST",
332
- headers: {
333
- "Content-Type": "application/x-www-form-urlencoded",
334
- Accept: "application/json",
335
- },
336
- body: new URLSearchParams({
337
- grant_type: "refresh_token",
338
- refresh_token: refreshToken,
339
- client_id: providerConfig.clientId,
340
- }).toString(),
341
- });
342
- if (!response.ok) {
343
- this.config.logger("[OAuthService] Token refresh failed", {
344
- status: response.status,
345
- provider: providerConfig.tokenUrl,
346
- });
347
- return null;
348
- }
349
- const tokens = await response.json();
350
- if (!tokens.access_token) {
351
- this.config.logger("[OAuthService] Token refresh response missing access_token");
352
- return null;
353
- }
354
- // Calculate expiration timestamp
355
- const expiresIn = tokens.expires_in || 3600; // Default 1 hour
356
- const expiresAt = Date.now() + expiresIn * 1000;
357
- const idpTokens = {
358
- access_token: tokens.access_token,
359
- refresh_token: tokens.refresh_token || refreshToken, // Use new refresh token if provided, otherwise keep old one
360
- expires_in: expiresIn,
361
- expires_at: expiresAt,
362
- token_type: tokens.token_type || "Bearer",
363
- scope: tokens.scope,
364
- };
365
- this.config.logger("[OAuthService] Token refresh successful", {
366
- provider: providerConfig.tokenUrl,
367
- expiresAt: new Date(expiresAt).toISOString(),
368
- });
369
- return idpTokens;
370
- }
371
- catch (error) {
372
- this.config.logger("[OAuthService] Token refresh error", {
373
- error: error instanceof Error ? error.message : String(error),
374
- provider: providerConfig.tokenUrl,
375
- });
376
- return null;
377
- }
378
- }
379
- /**
380
- * Refresh token via AgentShield proxy
381
- */
382
- async refreshTokenProxy(providerConfig, refreshToken) {
383
- const proxyUrl = `${this.config.agentShieldApiUrl}/api/v1/oauth/token`;
384
- this.config.logger("[OAuthService] Refreshing token via proxy", {
385
- proxyUrl,
386
- provider: providerConfig.authorizationUrl,
387
- });
388
- try {
389
- const response = await this.config.fetchProvider.fetch(proxyUrl, {
390
- method: "POST",
391
- headers: {
392
- "Content-Type": "application/json",
393
- Authorization: `Bearer ${this.config.agentShieldApiKey}`,
394
- },
395
- body: JSON.stringify({
396
- grant_type: "refresh_token",
397
- refresh_token: refreshToken,
398
- provider: providerConfig.authorizationUrl,
399
- project_id: this.config.projectId,
400
- }),
401
- });
402
- if (!response.ok) {
403
- this.config.logger("[OAuthService] Proxy token refresh failed", {
404
- status: response.status,
405
- proxyUrl,
406
- });
407
- return null;
408
- }
409
- const result = await response.json();
410
- const tokens = result.data || result;
411
- if (!tokens.access_token) {
412
- this.config.logger("[OAuthService] Proxy token refresh response missing access_token");
413
- return null;
414
- }
415
- // Calculate expiration timestamp
416
- const expiresIn = tokens.expires_in || 3600; // Default 1 hour
417
- const expiresAt = Date.now() + expiresIn * 1000;
418
- const idpTokens = {
419
- access_token: tokens.access_token,
420
- refresh_token: tokens.refresh_token || refreshToken,
421
- expires_in: expiresIn,
422
- expires_at: expiresAt,
423
- token_type: tokens.token_type || "Bearer",
424
- scope: tokens.scope,
425
- };
426
- this.config.logger("[OAuthService] Proxy token refresh successful", {
427
- proxyUrl,
428
- expiresAt: new Date(expiresAt).toISOString(),
429
- });
430
- return idpTokens;
431
- }
432
- catch (error) {
433
- this.config.logger("[OAuthService] Proxy token refresh error", {
434
- error: error instanceof Error ? error.message : String(error),
435
- proxyUrl,
436
- });
437
- return null;
438
- }
439
- }
440
- }
441
- exports.OAuthService = OAuthService;
442
- //# sourceMappingURL=oauth-service.js.map
@@ -1,49 +0,0 @@
1
- /**
2
- * OAuth Token Retrieval Service
3
- *
4
- * Retrieves OAuth tokens from AgentShield after receiving delegation token.
5
- * Implements the two-step token flow for Phase 3 custom IDP support.
6
- *
7
- * @package @kya-os/mcp-i-core
8
- */
9
- import type { IdpTokens } from "@kya-os/contracts/config";
10
- /**
11
- * Configuration for OAuthTokenRetrievalService
12
- */
13
- export interface OAuthTokenRetrievalServiceConfig {
14
- /** AgentShield API base URL */
15
- baseUrl: string;
16
- /** Fetch implementation */
17
- fetchProvider: typeof fetch;
18
- /** Optional logger callback */
19
- logger?: (message: string, data?: any) => void;
20
- /** Optional retry configuration */
21
- retryConfig?: {
22
- maxRetries?: number;
23
- retryDelay?: number;
24
- retryBackoff?: number;
25
- };
26
- }
27
- /**
28
- * Service for retrieving OAuth tokens from AgentShield
29
- */
30
- export declare class OAuthTokenRetrievalService {
31
- private config;
32
- constructor(config: OAuthTokenRetrievalServiceConfig);
33
- /**
34
- * Retrieve OAuth tokens from AgentShield
35
- *
36
- * @param delegationId - Delegation ID from token exchange response
37
- * @param delegationToken - Delegation token (JWT) for authorization
38
- * @returns OAuth tokens mapped to IdpTokens format, or null if unavailable
39
- */
40
- retrieveTokens(delegationId: string, delegationToken: string): Promise<IdpTokens | null>;
41
- /**
42
- * Map AgentShield response to IdpTokens format
43
- *
44
- * @param data - Response data from AgentShield
45
- * @returns IdpTokens object
46
- */
47
- private mapToIdpTokens;
48
- }
49
- //# sourceMappingURL=oauth-token-retrieval.service.d.ts.map
@@ -1,150 +0,0 @@
1
- "use strict";
2
- /**
3
- * OAuth Token Retrieval Service
4
- *
5
- * Retrieves OAuth tokens from AgentShield after receiving delegation token.
6
- * Implements the two-step token flow for Phase 3 custom IDP support.
7
- *
8
- * @package @kya-os/mcp-i-core
9
- */
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.OAuthTokenRetrievalService = void 0;
12
- /**
13
- * Service for retrieving OAuth tokens from AgentShield
14
- */
15
- class OAuthTokenRetrievalService {
16
- config;
17
- constructor(config) {
18
- const defaultRetryConfig = {
19
- maxRetries: 3,
20
- retryDelay: 1000,
21
- retryBackoff: 2,
22
- };
23
- this.config = {
24
- ...config,
25
- logger: config.logger || (() => { }),
26
- retryConfig: {
27
- ...defaultRetryConfig,
28
- ...config.retryConfig,
29
- },
30
- };
31
- }
32
- /**
33
- * Retrieve OAuth tokens from AgentShield
34
- *
35
- * @param delegationId - Delegation ID from token exchange response
36
- * @param delegationToken - Delegation token (JWT) for authorization
37
- * @returns OAuth tokens mapped to IdpTokens format, or null if unavailable
38
- */
39
- async retrieveTokens(delegationId, delegationToken) {
40
- const endpoint = `${this.config.baseUrl}/api/v1/bouncer/delegations/${delegationId}/tokens`;
41
- this.config.logger("[OAuthTokenRetrievalService] Retrieving OAuth tokens", {
42
- delegationId,
43
- endpoint,
44
- });
45
- let lastError = null;
46
- let attempt = 0;
47
- // Retry logic for transient failures
48
- while (attempt <= this.config.retryConfig.maxRetries) {
49
- try {
50
- const response = await this.config.fetchProvider(endpoint, {
51
- method: "GET",
52
- headers: {
53
- Authorization: `Bearer ${delegationToken}`,
54
- Accept: "application/json",
55
- },
56
- });
57
- if (!response.ok) {
58
- const errorData = await response.json().catch(() => ({}));
59
- if (response.status === 404 || response.status === 401) {
60
- // Token unavailable or unauthorized - don't retry
61
- this.config.logger("[OAuthTokenRetrievalService] Tokens unavailable", {
62
- status: response.status,
63
- delegationId,
64
- error: errorData,
65
- });
66
- return null;
67
- }
68
- // Transient error - retry
69
- const errorMessage = errorData.error?.message ||
70
- errorData.error ||
71
- errorData.message ||
72
- `HTTP ${response.status}`;
73
- throw new Error(`Token retrieval failed: ${errorMessage}`);
74
- }
75
- const result = (await response.json());
76
- if (!result.success) {
77
- this.config.logger("[OAuthTokenRetrievalService] Token retrieval error response", {
78
- delegationId,
79
- error: result.error,
80
- });
81
- return null;
82
- }
83
- // Map response to IdpTokens format
84
- const tokens = this.mapToIdpTokens(result.data);
85
- this.config.logger("[OAuthTokenRetrievalService] OAuth tokens retrieved successfully", {
86
- delegationId,
87
- expiresAt: new Date(tokens.expires_at).toISOString(),
88
- hasRefreshToken: !!tokens.refresh_token,
89
- });
90
- return tokens;
91
- }
92
- catch (error) {
93
- lastError = error instanceof Error ? error : new Error(String(error));
94
- if (attempt < this.config.retryConfig.maxRetries) {
95
- const delay = this.config.retryConfig.retryDelay *
96
- Math.pow(this.config.retryConfig.retryBackoff, attempt);
97
- this.config.logger("[OAuthTokenRetrievalService] Retry attempt failed, retrying", {
98
- attempt: attempt + 1,
99
- maxRetries: this.config.retryConfig.maxRetries,
100
- delay,
101
- error: lastError.message,
102
- });
103
- await new Promise((resolve) => setTimeout(resolve, delay));
104
- attempt++;
105
- }
106
- else {
107
- // Max retries exceeded
108
- this.config.logger("[OAuthTokenRetrievalService] Max retries exceeded", {
109
- delegationId,
110
- error: lastError.message,
111
- attempts: attempt + 1,
112
- });
113
- // Return null instead of throwing - delegation token still valid
114
- return null;
115
- }
116
- }
117
- }
118
- return null;
119
- }
120
- /**
121
- * Map AgentShield response to IdpTokens format
122
- *
123
- * @param data - Response data from AgentShield
124
- * @returns IdpTokens object
125
- */
126
- mapToIdpTokens(data) {
127
- // Convert ISO 8601 string to milliseconds timestamp
128
- let expiresAt;
129
- if (data.oauth_expires_at) {
130
- expiresAt = new Date(data.oauth_expires_at).getTime();
131
- }
132
- else if (data.oauth_expires_in) {
133
- expiresAt = Date.now() + data.oauth_expires_in * 1000;
134
- }
135
- else {
136
- // Default to 1 hour if neither provided
137
- expiresAt = Date.now() + 3600 * 1000;
138
- }
139
- return {
140
- access_token: data.oauth_access_token,
141
- refresh_token: data.oauth_refresh_token || undefined,
142
- expires_in: data.oauth_expires_in || undefined,
143
- expires_at: expiresAt,
144
- token_type: data.oauth_token_type || "Bearer",
145
- scope: data.oauth_scope || undefined,
146
- };
147
- }
148
- }
149
- exports.OAuthTokenRetrievalService = OAuthTokenRetrievalService;
150
- //# sourceMappingURL=oauth-token-retrieval.service.js.map