@mcp-z/oauth-microsoft 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +98 -0
  3. package/dist/cjs/index.d.cts +16 -0
  4. package/dist/cjs/index.d.ts +16 -0
  5. package/dist/cjs/index.js +112 -0
  6. package/dist/cjs/index.js.map +1 -0
  7. package/dist/cjs/lib/dcr-router.d.cts +44 -0
  8. package/dist/cjs/lib/dcr-router.d.ts +44 -0
  9. package/dist/cjs/lib/dcr-router.js +1227 -0
  10. package/dist/cjs/lib/dcr-router.js.map +1 -0
  11. package/dist/cjs/lib/dcr-utils.d.cts +160 -0
  12. package/dist/cjs/lib/dcr-utils.d.ts +160 -0
  13. package/dist/cjs/lib/dcr-utils.js +860 -0
  14. package/dist/cjs/lib/dcr-utils.js.map +1 -0
  15. package/dist/cjs/lib/dcr-verify.d.cts +53 -0
  16. package/dist/cjs/lib/dcr-verify.d.ts +53 -0
  17. package/dist/cjs/lib/dcr-verify.js +193 -0
  18. package/dist/cjs/lib/dcr-verify.js.map +1 -0
  19. package/dist/cjs/lib/fetch-with-timeout.d.cts +14 -0
  20. package/dist/cjs/lib/fetch-with-timeout.d.ts +14 -0
  21. package/dist/cjs/lib/fetch-with-timeout.js +257 -0
  22. package/dist/cjs/lib/fetch-with-timeout.js.map +1 -0
  23. package/dist/cjs/lib/token-verifier.d.cts +44 -0
  24. package/dist/cjs/lib/token-verifier.d.ts +44 -0
  25. package/dist/cjs/lib/token-verifier.js +253 -0
  26. package/dist/cjs/lib/token-verifier.js.map +1 -0
  27. package/dist/cjs/package.json +1 -0
  28. package/dist/cjs/providers/dcr.d.cts +110 -0
  29. package/dist/cjs/providers/dcr.d.ts +110 -0
  30. package/dist/cjs/providers/dcr.js +600 -0
  31. package/dist/cjs/providers/dcr.js.map +1 -0
  32. package/dist/cjs/providers/device-code.d.cts +179 -0
  33. package/dist/cjs/providers/device-code.d.ts +179 -0
  34. package/dist/cjs/providers/device-code.js +896 -0
  35. package/dist/cjs/providers/device-code.js.map +1 -0
  36. package/dist/cjs/providers/loopback-oauth.d.cts +125 -0
  37. package/dist/cjs/providers/loopback-oauth.d.ts +125 -0
  38. package/dist/cjs/providers/loopback-oauth.js +1325 -0
  39. package/dist/cjs/providers/loopback-oauth.js.map +1 -0
  40. package/dist/cjs/schemas/index.d.cts +20 -0
  41. package/dist/cjs/schemas/index.d.ts +20 -0
  42. package/dist/cjs/schemas/index.js +37 -0
  43. package/dist/cjs/schemas/index.js.map +1 -0
  44. package/dist/cjs/setup/config.d.cts +113 -0
  45. package/dist/cjs/setup/config.d.ts +113 -0
  46. package/dist/cjs/setup/config.js +246 -0
  47. package/dist/cjs/setup/config.js.map +1 -0
  48. package/dist/cjs/types.d.cts +188 -0
  49. package/dist/cjs/types.d.ts +188 -0
  50. package/dist/cjs/types.js +18 -0
  51. package/dist/cjs/types.js.map +1 -0
  52. package/dist/esm/index.d.ts +16 -0
  53. package/dist/esm/index.js +16 -0
  54. package/dist/esm/index.js.map +1 -0
  55. package/dist/esm/lib/dcr-router.d.ts +44 -0
  56. package/dist/esm/lib/dcr-router.js +556 -0
  57. package/dist/esm/lib/dcr-router.js.map +1 -0
  58. package/dist/esm/lib/dcr-utils.d.ts +160 -0
  59. package/dist/esm/lib/dcr-utils.js +270 -0
  60. package/dist/esm/lib/dcr-utils.js.map +1 -0
  61. package/dist/esm/lib/dcr-verify.d.ts +53 -0
  62. package/dist/esm/lib/dcr-verify.js +53 -0
  63. package/dist/esm/lib/dcr-verify.js.map +1 -0
  64. package/dist/esm/lib/fetch-with-timeout.d.ts +14 -0
  65. package/dist/esm/lib/fetch-with-timeout.js +30 -0
  66. package/dist/esm/lib/fetch-with-timeout.js.map +1 -0
  67. package/dist/esm/lib/token-verifier.d.ts +44 -0
  68. package/dist/esm/lib/token-verifier.js +53 -0
  69. package/dist/esm/lib/token-verifier.js.map +1 -0
  70. package/dist/esm/package.json +1 -0
  71. package/dist/esm/providers/dcr.d.ts +110 -0
  72. package/dist/esm/providers/dcr.js +235 -0
  73. package/dist/esm/providers/dcr.js.map +1 -0
  74. package/dist/esm/providers/device-code.d.ts +179 -0
  75. package/dist/esm/providers/device-code.js +417 -0
  76. package/dist/esm/providers/device-code.js.map +1 -0
  77. package/dist/esm/providers/loopback-oauth.d.ts +125 -0
  78. package/dist/esm/providers/loopback-oauth.js +643 -0
  79. package/dist/esm/providers/loopback-oauth.js.map +1 -0
  80. package/dist/esm/schemas/index.d.ts +20 -0
  81. package/dist/esm/schemas/index.js +18 -0
  82. package/dist/esm/schemas/index.js.map +1 -0
  83. package/dist/esm/setup/config.d.ts +113 -0
  84. package/dist/esm/setup/config.js +268 -0
  85. package/dist/esm/setup/config.js.map +1 -0
  86. package/dist/esm/types.d.ts +188 -0
  87. package/dist/esm/types.js +8 -0
  88. package/dist/esm/types.js.map +1 -0
  89. package/package.json +87 -0
@@ -0,0 +1,1325 @@
1
+ /**
2
+ * Loopback OAuth Implementation for Microsoft (RFC 8252)
3
+ *
4
+ * Implements OAuth 2.0 Authorization Code Flow with PKCE using loopback interface redirection.
5
+ * Uses ephemeral local server with OS-assigned port (RFC 8252 Section 8.3).
6
+ * Eliminates port conflicts by using port 0, allowing unlimited concurrent servers.
7
+ *
8
+ * Flow:
9
+ * 1. Check token cache (memory + storage)
10
+ * 2. If cache miss: Start ephemeral server on port 0
11
+ * 3. Generate auth URL with dynamic redirect (localhost:{assigned-port})
12
+ * 4. Open browser or print URL (headless flag controls behavior)
13
+ * 5. Handle callback, exchange code for token
14
+ * 6. Cache token to storage
15
+ * 7. Close ephemeral server
16
+ */ "use strict";
17
+ Object.defineProperty(exports, "__esModule", {
18
+ value: true
19
+ });
20
+ function _export(target, all) {
21
+ for(var name in all)Object.defineProperty(target, name, {
22
+ enumerable: true,
23
+ get: Object.getOwnPropertyDescriptor(all, name).get
24
+ });
25
+ }
26
+ _export(exports, {
27
+ get LoopbackOAuthProvider () {
28
+ return LoopbackOAuthProvider;
29
+ },
30
+ get createMicrosoftFileAuth () {
31
+ return createMicrosoftFileAuth;
32
+ }
33
+ });
34
+ var _oauth = require("@mcp-z/oauth");
35
+ var _http = /*#__PURE__*/ _interop_require_wildcard(require("http"));
36
+ var _open = /*#__PURE__*/ _interop_require_default(require("open"));
37
+ var _fetchwithtimeoutts = require("../lib/fetch-with-timeout.js");
38
+ var _typests = require("../types.js");
39
+ function _array_like_to_array(arr, len) {
40
+ if (len == null || len > arr.length) len = arr.length;
41
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
42
+ return arr2;
43
+ }
44
+ function _array_without_holes(arr) {
45
+ if (Array.isArray(arr)) return _array_like_to_array(arr);
46
+ }
47
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
48
+ try {
49
+ var info = gen[key](arg);
50
+ var value = info.value;
51
+ } catch (error) {
52
+ reject(error);
53
+ return;
54
+ }
55
+ if (info.done) {
56
+ resolve(value);
57
+ } else {
58
+ Promise.resolve(value).then(_next, _throw);
59
+ }
60
+ }
61
+ function _async_to_generator(fn) {
62
+ return function() {
63
+ var self = this, args = arguments;
64
+ return new Promise(function(resolve, reject) {
65
+ var gen = fn.apply(self, args);
66
+ function _next(value) {
67
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
68
+ }
69
+ function _throw(err) {
70
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
71
+ }
72
+ _next(undefined);
73
+ });
74
+ };
75
+ }
76
+ function _class_call_check(instance, Constructor) {
77
+ if (!(instance instanceof Constructor)) {
78
+ throw new TypeError("Cannot call a class as a function");
79
+ }
80
+ }
81
+ function _define_property(obj, key, value) {
82
+ if (key in obj) {
83
+ Object.defineProperty(obj, key, {
84
+ value: value,
85
+ enumerable: true,
86
+ configurable: true,
87
+ writable: true
88
+ });
89
+ } else {
90
+ obj[key] = value;
91
+ }
92
+ return obj;
93
+ }
94
+ function _instanceof(left, right) {
95
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
96
+ return !!right[Symbol.hasInstance](left);
97
+ } else {
98
+ return left instanceof right;
99
+ }
100
+ }
101
+ function _interop_require_default(obj) {
102
+ return obj && obj.__esModule ? obj : {
103
+ default: obj
104
+ };
105
+ }
106
+ function _getRequireWildcardCache(nodeInterop) {
107
+ if (typeof WeakMap !== "function") return null;
108
+ var cacheBabelInterop = new WeakMap();
109
+ var cacheNodeInterop = new WeakMap();
110
+ return (_getRequireWildcardCache = function(nodeInterop) {
111
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
112
+ })(nodeInterop);
113
+ }
114
+ function _interop_require_wildcard(obj, nodeInterop) {
115
+ if (!nodeInterop && obj && obj.__esModule) {
116
+ return obj;
117
+ }
118
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
119
+ return {
120
+ default: obj
121
+ };
122
+ }
123
+ var cache = _getRequireWildcardCache(nodeInterop);
124
+ if (cache && cache.has(obj)) {
125
+ return cache.get(obj);
126
+ }
127
+ var newObj = {
128
+ __proto__: null
129
+ };
130
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
131
+ for(var key in obj){
132
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
133
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
134
+ if (desc && (desc.get || desc.set)) {
135
+ Object.defineProperty(newObj, key, desc);
136
+ } else {
137
+ newObj[key] = obj[key];
138
+ }
139
+ }
140
+ }
141
+ newObj.default = obj;
142
+ if (cache) {
143
+ cache.set(obj, newObj);
144
+ }
145
+ return newObj;
146
+ }
147
+ function _iterable_to_array(iter) {
148
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
149
+ }
150
+ function _non_iterable_spread() {
151
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
152
+ }
153
+ function _object_spread(target) {
154
+ for(var i = 1; i < arguments.length; i++){
155
+ var source = arguments[i] != null ? arguments[i] : {};
156
+ var ownKeys = Object.keys(source);
157
+ if (typeof Object.getOwnPropertySymbols === "function") {
158
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
159
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
160
+ }));
161
+ }
162
+ ownKeys.forEach(function(key) {
163
+ _define_property(target, key, source[key]);
164
+ });
165
+ }
166
+ return target;
167
+ }
168
+ function ownKeys(object, enumerableOnly) {
169
+ var keys = Object.keys(object);
170
+ if (Object.getOwnPropertySymbols) {
171
+ var symbols = Object.getOwnPropertySymbols(object);
172
+ if (enumerableOnly) {
173
+ symbols = symbols.filter(function(sym) {
174
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
175
+ });
176
+ }
177
+ keys.push.apply(keys, symbols);
178
+ }
179
+ return keys;
180
+ }
181
+ function _object_spread_props(target, source) {
182
+ source = source != null ? source : {};
183
+ if (Object.getOwnPropertyDescriptors) {
184
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
185
+ } else {
186
+ ownKeys(Object(source)).forEach(function(key) {
187
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
188
+ });
189
+ }
190
+ return target;
191
+ }
192
+ function _to_consumable_array(arr) {
193
+ return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
194
+ }
195
+ function _type_of(obj) {
196
+ "@swc/helpers - typeof";
197
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
198
+ }
199
+ function _unsupported_iterable_to_array(o, minLen) {
200
+ if (!o) return;
201
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
202
+ var n = Object.prototype.toString.call(o).slice(8, -1);
203
+ if (n === "Object" && o.constructor) n = o.constructor.name;
204
+ if (n === "Map" || n === "Set") return Array.from(n);
205
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
206
+ }
207
+ function _ts_generator(thisArg, body) {
208
+ var f, y, t, _ = {
209
+ label: 0,
210
+ sent: function() {
211
+ if (t[0] & 1) throw t[1];
212
+ return t[1];
213
+ },
214
+ trys: [],
215
+ ops: []
216
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
217
+ return d(g, "next", {
218
+ value: verb(0)
219
+ }), d(g, "throw", {
220
+ value: verb(1)
221
+ }), d(g, "return", {
222
+ value: verb(2)
223
+ }), typeof Symbol === "function" && d(g, Symbol.iterator, {
224
+ value: function() {
225
+ return this;
226
+ }
227
+ }), g;
228
+ function verb(n) {
229
+ return function(v) {
230
+ return step([
231
+ n,
232
+ v
233
+ ]);
234
+ };
235
+ }
236
+ function step(op) {
237
+ if (f) throw new TypeError("Generator is already executing.");
238
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
239
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
240
+ if (y = 0, t) op = [
241
+ op[0] & 2,
242
+ t.value
243
+ ];
244
+ switch(op[0]){
245
+ case 0:
246
+ case 1:
247
+ t = op;
248
+ break;
249
+ case 4:
250
+ _.label++;
251
+ return {
252
+ value: op[1],
253
+ done: false
254
+ };
255
+ case 5:
256
+ _.label++;
257
+ y = op[1];
258
+ op = [
259
+ 0
260
+ ];
261
+ continue;
262
+ case 7:
263
+ op = _.ops.pop();
264
+ _.trys.pop();
265
+ continue;
266
+ default:
267
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
268
+ _ = 0;
269
+ continue;
270
+ }
271
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
272
+ _.label = op[1];
273
+ break;
274
+ }
275
+ if (op[0] === 6 && _.label < t[1]) {
276
+ _.label = t[1];
277
+ t = op;
278
+ break;
279
+ }
280
+ if (t && _.label < t[2]) {
281
+ _.label = t[2];
282
+ _.ops.push(op);
283
+ break;
284
+ }
285
+ if (t[2]) _.ops.pop();
286
+ _.trys.pop();
287
+ continue;
288
+ }
289
+ op = body.call(thisArg, _);
290
+ } catch (e) {
291
+ op = [
292
+ 6,
293
+ e
294
+ ];
295
+ y = 0;
296
+ } finally{
297
+ f = t = 0;
298
+ }
299
+ if (op[0] & 5) throw op[1];
300
+ return {
301
+ value: op[0] ? op[1] : void 0,
302
+ done: true
303
+ };
304
+ }
305
+ }
306
+ var LoopbackOAuthProvider = /*#__PURE__*/ function() {
307
+ "use strict";
308
+ function LoopbackOAuthProvider(config) {
309
+ _class_call_check(this, LoopbackOAuthProvider);
310
+ this.config = config;
311
+ }
312
+ var _proto = LoopbackOAuthProvider.prototype;
313
+ /**
314
+ * Get access token from Keyv using compound key
315
+ *
316
+ * @param accountId - Account identifier (email address). Required for loopback OAuth.
317
+ * @returns Access token for API requests
318
+ */ _proto.getAccessToken = function getAccessToken(accountId) {
319
+ return _async_to_generator(function() {
320
+ var _this_config, logger, service, tokenStore, effectiveAccountId, _tmp, storedToken, refreshedToken, error, headless, _this_config1, clientId, tenantId, scope, existingAccounts, hasOtherAccounts, authUrl, hint, baseDescriptor, descriptor, _ref, token, email;
321
+ return _ts_generator(this, function(_state) {
322
+ switch(_state.label){
323
+ case 0:
324
+ _this_config = this.config, logger = _this_config.logger, service = _this_config.service, tokenStore = _this_config.tokenStore;
325
+ if (!(accountId !== null && accountId !== void 0)) return [
326
+ 3,
327
+ 1
328
+ ];
329
+ _tmp = accountId;
330
+ return [
331
+ 3,
332
+ 3
333
+ ];
334
+ case 1:
335
+ return [
336
+ 4,
337
+ (0, _oauth.getActiveAccount)(tokenStore, {
338
+ service: service
339
+ })
340
+ ];
341
+ case 2:
342
+ _tmp = _state.sent();
343
+ _state.label = 3;
344
+ case 3:
345
+ effectiveAccountId = _tmp;
346
+ if (!effectiveAccountId) return [
347
+ 3,
348
+ 9
349
+ ];
350
+ logger.debug('Getting access token', {
351
+ service: service,
352
+ accountId: effectiveAccountId
353
+ });
354
+ return [
355
+ 4,
356
+ (0, _oauth.getToken)(tokenStore, {
357
+ accountId: effectiveAccountId,
358
+ service: service
359
+ })
360
+ ];
361
+ case 4:
362
+ storedToken = _state.sent();
363
+ if (storedToken && this.isTokenValid(storedToken)) {
364
+ logger.debug('Using stored access token', {
365
+ accountId: effectiveAccountId
366
+ });
367
+ return [
368
+ 2,
369
+ storedToken.accessToken
370
+ ];
371
+ }
372
+ if (!(storedToken === null || storedToken === void 0 ? void 0 : storedToken.refreshToken)) return [
373
+ 3,
374
+ 9
375
+ ];
376
+ _state.label = 5;
377
+ case 5:
378
+ _state.trys.push([
379
+ 5,
380
+ 8,
381
+ ,
382
+ 9
383
+ ]);
384
+ logger.info('Refreshing expired access token', {
385
+ accountId: effectiveAccountId
386
+ });
387
+ return [
388
+ 4,
389
+ this.refreshAccessToken(storedToken.refreshToken)
390
+ ];
391
+ case 6:
392
+ refreshedToken = _state.sent();
393
+ return [
394
+ 4,
395
+ (0, _oauth.setToken)(tokenStore, {
396
+ accountId: effectiveAccountId,
397
+ service: service
398
+ }, refreshedToken)
399
+ ];
400
+ case 7:
401
+ _state.sent();
402
+ return [
403
+ 2,
404
+ refreshedToken.accessToken
405
+ ];
406
+ case 8:
407
+ error = _state.sent();
408
+ logger.info('Token refresh failed, starting new OAuth flow', {
409
+ accountId: effectiveAccountId,
410
+ error: _instanceof(error, Error) ? error.message : String(error)
411
+ });
412
+ return [
413
+ 3,
414
+ 9
415
+ ];
416
+ case 9:
417
+ // No valid token or no account - check if we can start OAuth flow
418
+ headless = this.config.headless;
419
+ if (!headless) return [
420
+ 3,
421
+ 11
422
+ ];
423
+ // In headless mode (production), cannot start OAuth flow
424
+ // Throw AuthRequiredError with auth_url descriptor for MCP tool response
425
+ _this_config1 = this.config, clientId = _this_config1.clientId, tenantId = _this_config1.tenantId, scope = _this_config1.scope;
426
+ return [
427
+ 4,
428
+ this.getExistingAccounts()
429
+ ];
430
+ case 10:
431
+ existingAccounts = _state.sent();
432
+ hasOtherAccounts = effectiveAccountId ? existingAccounts.length > 0 && !existingAccounts.includes(effectiveAccountId) : existingAccounts.length > 0;
433
+ // Build informational OAuth URL for headless mode
434
+ // Note: No redirect_uri included - user must use account-add tool which starts proper ephemeral server
435
+ authUrl = new URL("https://login.microsoftonline.com/".concat(tenantId, "/oauth2/v2.0/authorize"));
436
+ authUrl.searchParams.set('client_id', clientId);
437
+ authUrl.searchParams.set('response_type', 'code');
438
+ authUrl.searchParams.set('scope', scope);
439
+ authUrl.searchParams.set('response_mode', 'query');
440
+ authUrl.searchParams.set('prompt', 'select_account');
441
+ if (hasOtherAccounts) {
442
+ hint = "Existing ".concat(service, " accounts found. Use account-list to view, account-switch to change account, or account-add to add new account");
443
+ } else if (effectiveAccountId) {
444
+ hint = "Use account-add to authenticate ".concat(effectiveAccountId);
445
+ } else {
446
+ hint = 'Use account-add to authenticate interactively';
447
+ }
448
+ baseDescriptor = {
449
+ kind: 'auth_url',
450
+ provider: 'microsoft',
451
+ url: authUrl.toString(),
452
+ hint: hint
453
+ };
454
+ descriptor = effectiveAccountId ? _object_spread_props(_object_spread({}, baseDescriptor), {
455
+ accountId: effectiveAccountId
456
+ }) : baseDescriptor;
457
+ throw new _typests.AuthRequiredError(descriptor);
458
+ case 11:
459
+ // Interactive mode - start ephemeral OAuth flow
460
+ logger.info('Starting ephemeral OAuth flow', {
461
+ service: service,
462
+ headless: headless
463
+ });
464
+ return [
465
+ 4,
466
+ this.performEphemeralOAuthFlow()
467
+ ];
468
+ case 12:
469
+ _ref = _state.sent(), token = _ref.token, email = _ref.email;
470
+ // Store token with email as accountId
471
+ return [
472
+ 4,
473
+ (0, _oauth.setToken)(tokenStore, {
474
+ accountId: email,
475
+ service: service
476
+ }, token)
477
+ ];
478
+ case 13:
479
+ _state.sent();
480
+ // Register account in account management system
481
+ return [
482
+ 4,
483
+ (0, _oauth.addAccount)(tokenStore, {
484
+ service: service,
485
+ accountId: email
486
+ })
487
+ ];
488
+ case 14:
489
+ _state.sent();
490
+ // Set as active account so subsequent getAccessToken() calls find it
491
+ return [
492
+ 4,
493
+ (0, _oauth.setActiveAccount)(tokenStore, {
494
+ service: service,
495
+ accountId: email
496
+ })
497
+ ];
498
+ case 15:
499
+ _state.sent();
500
+ // Store account metadata (email, added timestamp)
501
+ return [
502
+ 4,
503
+ (0, _oauth.setAccountInfo)(tokenStore, {
504
+ service: service,
505
+ accountId: email
506
+ }, {
507
+ email: email,
508
+ addedAt: new Date().toISOString()
509
+ })
510
+ ];
511
+ case 16:
512
+ _state.sent();
513
+ logger.info('OAuth flow completed', {
514
+ service: service,
515
+ accountId: email
516
+ });
517
+ return [
518
+ 2,
519
+ token.accessToken
520
+ ];
521
+ }
522
+ });
523
+ }).call(this);
524
+ };
525
+ /**
526
+ * Convert to Microsoft Graph-compatible auth provider
527
+ *
528
+ * @param accountId - Account identifier for multi-account support (e.g., 'user@example.com')
529
+ * @returns Auth provider configured for the specified account
530
+ */ _proto.toAuthProvider = function toAuthProvider(accountId) {
531
+ var _this = this;
532
+ // Capture accountId in closure to pass to getAccessToken
533
+ var getToken = function() {
534
+ return _this.getAccessToken(accountId);
535
+ };
536
+ return {
537
+ getAccessToken: getToken
538
+ };
539
+ };
540
+ /**
541
+ * Authenticate new account with OAuth flow
542
+ * Triggers account selection, stores token, registers account
543
+ *
544
+ * @returns Email address of newly authenticated account
545
+ * @throws Error in headless mode (cannot open browser for OAuth)
546
+ */ _proto.authenticateNewAccount = function authenticateNewAccount() {
547
+ return _async_to_generator(function() {
548
+ var _this_config, logger, headless, service, tokenStore, _ref, token, email;
549
+ return _ts_generator(this, function(_state) {
550
+ switch(_state.label){
551
+ case 0:
552
+ _this_config = this.config, logger = _this_config.logger, headless = _this_config.headless, service = _this_config.service, tokenStore = _this_config.tokenStore;
553
+ if (headless) {
554
+ throw new Error('Cannot authenticate new account in headless mode - interactive OAuth required');
555
+ }
556
+ logger.info('Starting new account authentication', {
557
+ service: service
558
+ });
559
+ return [
560
+ 4,
561
+ this.performEphemeralOAuthFlow()
562
+ ];
563
+ case 1:
564
+ _ref = _state.sent(), token = _ref.token, email = _ref.email;
565
+ // Store token
566
+ return [
567
+ 4,
568
+ (0, _oauth.setToken)(tokenStore, {
569
+ accountId: email,
570
+ service: service
571
+ }, token)
572
+ ];
573
+ case 2:
574
+ _state.sent();
575
+ // Register account
576
+ return [
577
+ 4,
578
+ (0, _oauth.addAccount)(tokenStore, {
579
+ service: service,
580
+ accountId: email
581
+ })
582
+ ];
583
+ case 3:
584
+ _state.sent();
585
+ // Set as active account
586
+ return [
587
+ 4,
588
+ (0, _oauth.setActiveAccount)(tokenStore, {
589
+ service: service,
590
+ accountId: email
591
+ })
592
+ ];
593
+ case 4:
594
+ _state.sent();
595
+ // Store account metadata
596
+ return [
597
+ 4,
598
+ (0, _oauth.setAccountInfo)(tokenStore, {
599
+ service: service,
600
+ accountId: email
601
+ }, {
602
+ email: email,
603
+ addedAt: new Date().toISOString()
604
+ })
605
+ ];
606
+ case 5:
607
+ _state.sent();
608
+ logger.info('New account authenticated', {
609
+ service: service,
610
+ email: email
611
+ });
612
+ return [
613
+ 2,
614
+ email
615
+ ];
616
+ }
617
+ });
618
+ }).call(this);
619
+ };
620
+ /**
621
+ * Get user email from Microsoft Graph API (pure query)
622
+ * Used to query email for existing authenticated account
623
+ *
624
+ * @param accountId - Account identifier to get email for
625
+ * @returns User's email address
626
+ */ _proto.getUserEmail = function getUserEmail(accountId) {
627
+ return _async_to_generator(function() {
628
+ var _userInfo_mail, token, response, _, _1, _2, userInfo;
629
+ return _ts_generator(this, function(_state) {
630
+ switch(_state.label){
631
+ case 0:
632
+ return [
633
+ 4,
634
+ this.getAccessToken(accountId)
635
+ ];
636
+ case 1:
637
+ token = _state.sent();
638
+ return [
639
+ 4,
640
+ (0, _fetchwithtimeoutts.fetchWithTimeout)('https://graph.microsoft.com/v1.0/me', {
641
+ headers: {
642
+ Authorization: "Bearer ".concat(token)
643
+ }
644
+ })
645
+ ];
646
+ case 2:
647
+ response = _state.sent();
648
+ if (!!response.ok) return [
649
+ 3,
650
+ 4
651
+ ];
652
+ _ = Error.bind;
653
+ _2 = (_1 = "Failed to get user info: ".concat(response.status, " ")).concat;
654
+ return [
655
+ 4,
656
+ response.text()
657
+ ];
658
+ case 3:
659
+ throw new (_.apply(Error, [
660
+ void 0,
661
+ _2.apply(_1, [
662
+ _state.sent()
663
+ ])
664
+ ]));
665
+ case 4:
666
+ return [
667
+ 4,
668
+ response.json()
669
+ ];
670
+ case 5:
671
+ userInfo = _state.sent();
672
+ return [
673
+ 2,
674
+ (_userInfo_mail = userInfo.mail) !== null && _userInfo_mail !== void 0 ? _userInfo_mail : userInfo.userPrincipalName
675
+ ];
676
+ }
677
+ });
678
+ }).call(this);
679
+ };
680
+ /**
681
+ * Check for existing accounts in token storage (incremental OAuth detection)
682
+ *
683
+ * Uses key-utils helper for forward compatibility with key format changes.
684
+ *
685
+ * @returns Array of account IDs that have tokens for this service
686
+ */ _proto.getExistingAccounts = function getExistingAccounts() {
687
+ return _async_to_generator(function() {
688
+ var _this_config, service, tokenStore;
689
+ return _ts_generator(this, function(_state) {
690
+ _this_config = this.config, service = _this_config.service, tokenStore = _this_config.tokenStore;
691
+ return [
692
+ 2,
693
+ (0, _oauth.listAccountIds)(tokenStore, service)
694
+ ];
695
+ });
696
+ }).call(this);
697
+ };
698
+ _proto.isTokenValid = function isTokenValid(token) {
699
+ if (!token.expiresAt) return true; // No expiry = assume valid
700
+ return Date.now() < token.expiresAt - 60000; // 1 minute buffer
701
+ };
702
+ /**
703
+ * Fetch user email from Microsoft Graph using access token
704
+ * Called during OAuth flow to get email for accountId
705
+ *
706
+ * @param accessToken - Fresh access token from OAuth exchange
707
+ * @returns User's email address (mail field or userPrincipalName fallback)
708
+ */ _proto.fetchUserEmailFromToken = function fetchUserEmailFromToken(accessToken) {
709
+ return _async_to_generator(function() {
710
+ var _userInfo_mail, logger, response, errorText, userInfo, email;
711
+ return _ts_generator(this, function(_state) {
712
+ switch(_state.label){
713
+ case 0:
714
+ logger = this.config.logger;
715
+ return [
716
+ 4,
717
+ (0, _fetchwithtimeoutts.fetchWithTimeout)('https://graph.microsoft.com/v1.0/me', {
718
+ headers: {
719
+ Authorization: "Bearer ".concat(accessToken)
720
+ }
721
+ })
722
+ ];
723
+ case 1:
724
+ response = _state.sent();
725
+ if (!!response.ok) return [
726
+ 3,
727
+ 3
728
+ ];
729
+ return [
730
+ 4,
731
+ response.text()
732
+ ];
733
+ case 2:
734
+ errorText = _state.sent();
735
+ throw new Error("Failed to fetch user email: HTTP ".concat(response.status, " - ").concat(errorText));
736
+ case 3:
737
+ return [
738
+ 4,
739
+ response.json()
740
+ ];
741
+ case 4:
742
+ userInfo = _state.sent();
743
+ email = (_userInfo_mail = userInfo.mail) !== null && _userInfo_mail !== void 0 ? _userInfo_mail : userInfo.userPrincipalName;
744
+ logger.debug('Fetched user email from Graph API', {
745
+ email: email
746
+ });
747
+ return [
748
+ 2,
749
+ email
750
+ ];
751
+ }
752
+ });
753
+ }).call(this);
754
+ };
755
+ _proto.performEphemeralOAuthFlow = function performEphemeralOAuthFlow() {
756
+ return _async_to_generator(function() {
757
+ var _this, _this_config, clientId, tenantId, scope, headless, logger, configRedirectUri, targetHost, targetPort, targetProtocol, callbackPath, useConfiguredUri, parsed;
758
+ return _ts_generator(this, function(_state) {
759
+ _this = this;
760
+ _this_config = this.config, clientId = _this_config.clientId, tenantId = _this_config.tenantId, scope = _this_config.scope, headless = _this_config.headless, logger = _this_config.logger, configRedirectUri = _this_config.redirectUri;
761
+ // Parse redirectUri if provided to extract host, protocol, port, and path
762
+ targetHost = 'localhost'; // Default: localhost (Microsoft requires exact match with registered redirect URI)
763
+ targetPort = 0; // Default: OS-assigned ephemeral port
764
+ targetProtocol = 'http:'; // Default: http
765
+ callbackPath = '/callback'; // Default callback path
766
+ useConfiguredUri = false;
767
+ if (configRedirectUri) {
768
+ try {
769
+ parsed = new URL(configRedirectUri);
770
+ // Use configured redirect URI as-is for production deployments
771
+ targetHost = parsed.hostname;
772
+ targetProtocol = parsed.protocol;
773
+ // Extract port from URL (use default ports if not specified)
774
+ if (parsed.port) {
775
+ targetPort = Number.parseInt(parsed.port, 10);
776
+ } else {
777
+ targetPort = parsed.protocol === 'https:' ? 443 : 80;
778
+ }
779
+ // Extract path (default to /callback if URL has no path or just '/')
780
+ if (parsed.pathname && parsed.pathname !== '/') {
781
+ callbackPath = parsed.pathname;
782
+ }
783
+ useConfiguredUri = true;
784
+ logger.debug('Using configured redirect URI', {
785
+ host: targetHost,
786
+ protocol: targetProtocol,
787
+ port: targetPort,
788
+ path: callbackPath,
789
+ redirectUri: configRedirectUri
790
+ });
791
+ } catch (error) {
792
+ logger.warn('Failed to parse redirectUri, using ephemeral defaults', {
793
+ redirectUri: configRedirectUri,
794
+ error: _instanceof(error, Error) ? error.message : String(error)
795
+ });
796
+ // Continue with defaults (127.0.0.1, port 0, http, /callback)
797
+ }
798
+ }
799
+ return [
800
+ 2,
801
+ new Promise(function(resolve, reject) {
802
+ // Generate PKCE challenge
803
+ var _generatePKCE = (0, _oauth.generatePKCE)(), codeVerifier = _generatePKCE.verifier, codeChallenge = _generatePKCE.challenge;
804
+ var server = null;
805
+ var serverPort;
806
+ var finalRedirectUri; // Will be set in server.listen callback
807
+ // Create ephemeral server with OS-assigned port (RFC 8252)
808
+ server = _http.createServer(function(req, res) {
809
+ return _async_to_generator(function() {
810
+ var url, code, _$error, tokenResponse, cachedToken, email, exchangeError;
811
+ return _ts_generator(this, function(_state) {
812
+ switch(_state.label){
813
+ case 0:
814
+ if (!req.url) {
815
+ res.writeHead(400, {
816
+ 'Content-Type': 'text/html'
817
+ });
818
+ res.end((0, _oauth.getErrorTemplate)('Invalid request'));
819
+ server === null || server === void 0 ? void 0 : server.close();
820
+ reject(new Error('Invalid request: missing URL'));
821
+ return [
822
+ 2
823
+ ];
824
+ }
825
+ url = new URL(req.url, "http://localhost:".concat(serverPort));
826
+ if (!(url.pathname === callbackPath)) return [
827
+ 3,
828
+ 6
829
+ ];
830
+ code = url.searchParams.get('code');
831
+ _$error = url.searchParams.get('error');
832
+ if (_$error) {
833
+ res.writeHead(400, {
834
+ 'Content-Type': 'text/html'
835
+ });
836
+ res.end((0, _oauth.getErrorTemplate)(_$error));
837
+ server === null || server === void 0 ? void 0 : server.close();
838
+ reject(new Error("OAuth error: ".concat(_$error)));
839
+ return [
840
+ 2
841
+ ];
842
+ }
843
+ if (!code) {
844
+ res.writeHead(400, {
845
+ 'Content-Type': 'text/html'
846
+ });
847
+ res.end((0, _oauth.getErrorTemplate)('No authorization code received'));
848
+ server === null || server === void 0 ? void 0 : server.close();
849
+ reject(new Error('No authorization code received'));
850
+ return [
851
+ 2
852
+ ];
853
+ }
854
+ _state.label = 1;
855
+ case 1:
856
+ _state.trys.push([
857
+ 1,
858
+ 4,
859
+ ,
860
+ 5
861
+ ]);
862
+ return [
863
+ 4,
864
+ this.exchangeCodeForToken(code, codeVerifier, finalRedirectUri)
865
+ ];
866
+ case 2:
867
+ tokenResponse = _state.sent();
868
+ // Build cached token
869
+ cachedToken = _object_spread({
870
+ accessToken: tokenResponse.access_token
871
+ }, tokenResponse.refresh_token !== undefined && {
872
+ refreshToken: tokenResponse.refresh_token
873
+ }, tokenResponse.expires_in !== undefined && {
874
+ expiresAt: Date.now() + tokenResponse.expires_in * 1000
875
+ }, tokenResponse.scope !== undefined && {
876
+ scope: tokenResponse.scope
877
+ });
878
+ return [
879
+ 4,
880
+ this.fetchUserEmailFromToken(tokenResponse.access_token)
881
+ ];
882
+ case 3:
883
+ email = _state.sent();
884
+ res.writeHead(200, {
885
+ 'Content-Type': 'text/html'
886
+ });
887
+ res.end((0, _oauth.getSuccessTemplate)());
888
+ server === null || server === void 0 ? void 0 : server.close();
889
+ resolve({
890
+ token: cachedToken,
891
+ email: email
892
+ });
893
+ return [
894
+ 3,
895
+ 5
896
+ ];
897
+ case 4:
898
+ exchangeError = _state.sent();
899
+ logger.error('Token exchange failed', {
900
+ error: _instanceof(exchangeError, Error) ? exchangeError.message : String(exchangeError)
901
+ });
902
+ res.writeHead(500, {
903
+ 'Content-Type': 'text/html'
904
+ });
905
+ res.end((0, _oauth.getErrorTemplate)('Token exchange failed'));
906
+ server === null || server === void 0 ? void 0 : server.close();
907
+ reject(exchangeError);
908
+ return [
909
+ 3,
910
+ 5
911
+ ];
912
+ case 5:
913
+ return [
914
+ 3,
915
+ 7
916
+ ];
917
+ case 6:
918
+ res.writeHead(404, {
919
+ 'Content-Type': 'text/plain'
920
+ });
921
+ res.end('Not Found');
922
+ _state.label = 7;
923
+ case 7:
924
+ return [
925
+ 2
926
+ ];
927
+ }
928
+ });
929
+ }).call(_this);
930
+ });
931
+ // Listen on targetPort (0 for OS assignment, or custom port from redirectUri)
932
+ server.listen(targetPort, targetHost, function() {
933
+ var address = server === null || server === void 0 ? void 0 : server.address();
934
+ if (!address || typeof address === 'string') {
935
+ server === null || server === void 0 ? void 0 : server.close();
936
+ reject(new Error('Failed to start ephemeral server'));
937
+ return;
938
+ }
939
+ serverPort = address.port;
940
+ // Construct final redirect URI
941
+ if (useConfiguredUri && configRedirectUri) {
942
+ // Use configured redirect URI as-is for production
943
+ finalRedirectUri = configRedirectUri;
944
+ } else {
945
+ // Construct ephemeral redirect URI with actual server port
946
+ finalRedirectUri = "".concat(targetProtocol, "//").concat(targetHost, ":").concat(serverPort).concat(callbackPath);
947
+ }
948
+ // Build Microsoft auth URL
949
+ var authUrl = new URL("https://login.microsoftonline.com/".concat(tenantId, "/oauth2/v2.0/authorize"));
950
+ authUrl.searchParams.set('client_id', clientId);
951
+ authUrl.searchParams.set('redirect_uri', finalRedirectUri);
952
+ authUrl.searchParams.set('response_type', 'code');
953
+ authUrl.searchParams.set('scope', scope);
954
+ authUrl.searchParams.set('response_mode', 'query');
955
+ authUrl.searchParams.set('code_challenge', codeChallenge);
956
+ authUrl.searchParams.set('code_challenge_method', 'S256');
957
+ authUrl.searchParams.set('prompt', 'select_account');
958
+ logger.info('Ephemeral OAuth server started', {
959
+ port: serverPort,
960
+ headless: headless
961
+ });
962
+ if (headless) {
963
+ // Headless mode: Print auth URL to stderr (stdout is MCP protocol)
964
+ console.error('\n🔐 OAuth Authorization Required');
965
+ console.error('📋 Please visit this URL in your browser:\n');
966
+ console.error(" ".concat(authUrl.toString(), "\n"));
967
+ console.error('⏳ Waiting for authorization...\n');
968
+ } else {
969
+ // Interactive mode: Open browser automatically
970
+ logger.info('Opening browser for OAuth authorization');
971
+ (0, _open.default)(authUrl.toString()).catch(function(error) {
972
+ logger.info('Failed to open browser automatically', {
973
+ error: error.message
974
+ });
975
+ console.error('\n🔐 OAuth Authorization Required');
976
+ console.error(" ".concat(authUrl.toString(), "\n"));
977
+ });
978
+ }
979
+ });
980
+ // Timeout after 5 minutes
981
+ setTimeout(function() {
982
+ if (server) {
983
+ server.close();
984
+ reject(new Error('OAuth flow timed out after 5 minutes'));
985
+ }
986
+ }, 5 * 60 * 1000);
987
+ })
988
+ ];
989
+ });
990
+ }).call(this);
991
+ };
992
+ _proto.exchangeCodeForToken = function exchangeCodeForToken(code, codeVerifier, redirectUri) {
993
+ return _async_to_generator(function() {
994
+ var _this_config, clientId, clientSecret, tenantId, tokenUrl, params, body, response, errorText;
995
+ return _ts_generator(this, function(_state) {
996
+ switch(_state.label){
997
+ case 0:
998
+ _this_config = this.config, clientId = _this_config.clientId, clientSecret = _this_config.clientSecret, tenantId = _this_config.tenantId;
999
+ tokenUrl = "https://login.microsoftonline.com/".concat(tenantId, "/oauth2/v2.0/token");
1000
+ params = {
1001
+ code: code,
1002
+ client_id: clientId,
1003
+ redirect_uri: redirectUri,
1004
+ grant_type: 'authorization_code',
1005
+ code_verifier: codeVerifier
1006
+ };
1007
+ // Only include client_secret for confidential clients
1008
+ if (clientSecret) {
1009
+ params.client_secret = clientSecret;
1010
+ }
1011
+ body = new URLSearchParams(params);
1012
+ return [
1013
+ 4,
1014
+ (0, _fetchwithtimeoutts.fetchWithTimeout)(tokenUrl, {
1015
+ method: 'POST',
1016
+ headers: {
1017
+ 'Content-Type': 'application/x-www-form-urlencoded'
1018
+ },
1019
+ body: body.toString()
1020
+ })
1021
+ ];
1022
+ case 1:
1023
+ response = _state.sent();
1024
+ if (!!response.ok) return [
1025
+ 3,
1026
+ 3
1027
+ ];
1028
+ return [
1029
+ 4,
1030
+ response.text()
1031
+ ];
1032
+ case 2:
1033
+ errorText = _state.sent();
1034
+ throw new Error("Token exchange failed: ".concat(response.status, " ").concat(errorText));
1035
+ case 3:
1036
+ return [
1037
+ 4,
1038
+ response.json()
1039
+ ];
1040
+ case 4:
1041
+ return [
1042
+ 2,
1043
+ _state.sent()
1044
+ ];
1045
+ }
1046
+ });
1047
+ }).call(this);
1048
+ };
1049
+ _proto.refreshAccessToken = function refreshAccessToken(refreshToken) {
1050
+ return _async_to_generator(function() {
1051
+ var _this_config, clientId, clientSecret, tenantId, scope, tokenUrl, params, body, response, errorText, tokenResponse;
1052
+ return _ts_generator(this, function(_state) {
1053
+ switch(_state.label){
1054
+ case 0:
1055
+ _this_config = this.config, clientId = _this_config.clientId, clientSecret = _this_config.clientSecret, tenantId = _this_config.tenantId, scope = _this_config.scope;
1056
+ tokenUrl = "https://login.microsoftonline.com/".concat(tenantId, "/oauth2/v2.0/token");
1057
+ params = {
1058
+ refresh_token: refreshToken,
1059
+ client_id: clientId,
1060
+ grant_type: 'refresh_token',
1061
+ scope: scope
1062
+ };
1063
+ // Only include client_secret for confidential clients
1064
+ if (clientSecret) {
1065
+ params.client_secret = clientSecret;
1066
+ }
1067
+ body = new URLSearchParams(params);
1068
+ return [
1069
+ 4,
1070
+ (0, _fetchwithtimeoutts.fetchWithTimeout)(tokenUrl, {
1071
+ method: 'POST',
1072
+ headers: {
1073
+ 'Content-Type': 'application/x-www-form-urlencoded'
1074
+ },
1075
+ body: body.toString()
1076
+ })
1077
+ ];
1078
+ case 1:
1079
+ response = _state.sent();
1080
+ if (!!response.ok) return [
1081
+ 3,
1082
+ 3
1083
+ ];
1084
+ return [
1085
+ 4,
1086
+ response.text()
1087
+ ];
1088
+ case 2:
1089
+ errorText = _state.sent();
1090
+ throw new Error("Token refresh failed: ".concat(response.status, " ").concat(errorText));
1091
+ case 3:
1092
+ return [
1093
+ 4,
1094
+ response.json()
1095
+ ];
1096
+ case 4:
1097
+ tokenResponse = _state.sent();
1098
+ return [
1099
+ 2,
1100
+ _object_spread({
1101
+ accessToken: tokenResponse.access_token,
1102
+ refreshToken: refreshToken
1103
+ }, tokenResponse.expires_in !== undefined && {
1104
+ expiresAt: Date.now() + tokenResponse.expires_in * 1000
1105
+ }, tokenResponse.scope !== undefined && {
1106
+ scope: tokenResponse.scope
1107
+ })
1108
+ ];
1109
+ }
1110
+ });
1111
+ }).call(this);
1112
+ };
1113
+ /**
1114
+ * Create auth middleware for single-user context (single active account per service)
1115
+ *
1116
+ * Single-user mode:
1117
+ * - Maintains per-service active accounts in storage
1118
+ * - Supports backchannel account override via extra._meta.accountId
1119
+ * - Automatically enhances output schemas with auth_required branch
1120
+ *
1121
+ * Example:
1122
+ * ```typescript
1123
+ * const loopback = new LoopbackOAuthProvider({ service: 'outlook', ... });
1124
+ * const middleware = loopback.authMiddleware();
1125
+ * const tools = toolFactories.map(f => f()).map(middleware.withToolAuth);
1126
+ * const resources = resourceFactories.map(f => f()).map(middleware.withResourceAuth);
1127
+ * const prompts = promptFactories.map(f => f()).map(middleware.withPromptAuth);
1128
+ * ```
1129
+ *
1130
+ * @returns Object with withToolAuth, withResourceAuth, withPromptAuth methods
1131
+ */ _proto.authMiddleware = function authMiddleware() {
1132
+ var _this = this;
1133
+ var _this_config = this.config, service = _this_config.service, tokenStore = _this_config.tokenStore, logger = _this_config.logger;
1134
+ // Shared wrapper logic - extracts extra parameter from specified position
1135
+ // Generic T captures the actual module type; handler is cast from unknown to callable
1136
+ var wrapAtPosition = function(module, extraPosition) {
1137
+ var _this1 = _this;
1138
+ var operation = module.name;
1139
+ var originalHandler = module.handler;
1140
+ var wrappedHandler = function() {
1141
+ for(var _len = arguments.length, allArgs = new Array(_len), _key = 0; _key < _len; _key++){
1142
+ allArgs[_key] = arguments[_key];
1143
+ }
1144
+ return _async_to_generator(function() {
1145
+ var extra, accountId, _ref, _extra__meta, _tmp, error, effectiveAccountId, _tmp1, auth, error1, authRequiredResponse;
1146
+ return _ts_generator(this, function(_state) {
1147
+ switch(_state.label){
1148
+ case 0:
1149
+ if (allArgs.length <= extraPosition) {
1150
+ // Arg-less tool pattern: keep args as-is, create separate extra object
1151
+ extra = allArgs[0] && _type_of(allArgs[0]) === 'object' ? {} : {};
1152
+ allArgs[extraPosition] = extra;
1153
+ } else {
1154
+ extra = allArgs[extraPosition] || {};
1155
+ allArgs[extraPosition] = extra;
1156
+ }
1157
+ _state.label = 1;
1158
+ case 1:
1159
+ _state.trys.push([
1160
+ 1,
1161
+ 13,
1162
+ ,
1163
+ 14
1164
+ ]);
1165
+ _state.label = 2;
1166
+ case 2:
1167
+ _state.trys.push([
1168
+ 2,
1169
+ 6,
1170
+ ,
1171
+ 7
1172
+ ]);
1173
+ if (!((_ref = (_extra__meta = extra._meta) === null || _extra__meta === void 0 ? void 0 : _extra__meta.accountId) !== null && _ref !== void 0)) return [
1174
+ 3,
1175
+ 3
1176
+ ];
1177
+ _tmp = _ref;
1178
+ return [
1179
+ 3,
1180
+ 5
1181
+ ];
1182
+ case 3:
1183
+ return [
1184
+ 4,
1185
+ (0, _oauth.getActiveAccount)(tokenStore, {
1186
+ service: service
1187
+ })
1188
+ ];
1189
+ case 4:
1190
+ _tmp = _state.sent();
1191
+ _state.label = 5;
1192
+ case 5:
1193
+ accountId = _tmp;
1194
+ return [
1195
+ 3,
1196
+ 7
1197
+ ];
1198
+ case 6:
1199
+ error = _state.sent();
1200
+ if (_instanceof(error, Error) && (error.code === 'REQUIRES_AUTHENTICATION' || error.name === 'AccountManagerError')) {
1201
+ accountId = undefined;
1202
+ } else {
1203
+ throw error;
1204
+ }
1205
+ return [
1206
+ 3,
1207
+ 7
1208
+ ];
1209
+ case 7:
1210
+ // Eagerly validate token exists or trigger OAuth flow
1211
+ return [
1212
+ 4,
1213
+ this.getAccessToken(accountId)
1214
+ ];
1215
+ case 8:
1216
+ _state.sent();
1217
+ if (!(accountId !== null && accountId !== void 0)) return [
1218
+ 3,
1219
+ 9
1220
+ ];
1221
+ _tmp1 = accountId;
1222
+ return [
1223
+ 3,
1224
+ 11
1225
+ ];
1226
+ case 9:
1227
+ return [
1228
+ 4,
1229
+ (0, _oauth.getActiveAccount)(tokenStore, {
1230
+ service: service
1231
+ })
1232
+ ];
1233
+ case 10:
1234
+ _tmp1 = _state.sent();
1235
+ _state.label = 11;
1236
+ case 11:
1237
+ effectiveAccountId = _tmp1;
1238
+ if (!effectiveAccountId) {
1239
+ throw new Error("No account found after OAuth flow for service ".concat(service));
1240
+ }
1241
+ auth = this.toAuthProvider(effectiveAccountId);
1242
+ // Inject authContext and logger into extra
1243
+ extra.authContext = {
1244
+ auth: auth,
1245
+ accountId: effectiveAccountId
1246
+ };
1247
+ extra.logger = logger;
1248
+ return [
1249
+ 4,
1250
+ originalHandler.apply(void 0, _to_consumable_array(allArgs))
1251
+ ];
1252
+ case 12:
1253
+ // Call original handler with all args
1254
+ return [
1255
+ 2,
1256
+ _state.sent()
1257
+ ];
1258
+ case 13:
1259
+ error1 = _state.sent();
1260
+ // Token retrieval/refresh failed - return auth required
1261
+ if (_instanceof(error1, _typests.AuthRequiredError)) {
1262
+ logger.info('Authentication required', {
1263
+ service: service,
1264
+ tool: operation,
1265
+ descriptor: error1.descriptor
1266
+ });
1267
+ // Return auth_required response wrapped in { result } to match tool outputSchema pattern
1268
+ // Tools define outputSchema: z.object({ result: discriminatedUnion(...) }) where auth_required is a branch
1269
+ authRequiredResponse = {
1270
+ type: 'auth_required',
1271
+ provider: service,
1272
+ message: "Authentication required for ".concat(operation, ". Please authenticate with ").concat(service, "."),
1273
+ url: error1.descriptor.kind === 'auth_url' ? error1.descriptor.url : undefined
1274
+ };
1275
+ return [
1276
+ 2,
1277
+ {
1278
+ content: [
1279
+ {
1280
+ type: 'text',
1281
+ text: JSON.stringify({
1282
+ result: authRequiredResponse
1283
+ })
1284
+ }
1285
+ ],
1286
+ structuredContent: {
1287
+ result: authRequiredResponse
1288
+ }
1289
+ }
1290
+ ];
1291
+ }
1292
+ // Other errors - propagate
1293
+ throw error1;
1294
+ case 14:
1295
+ return [
1296
+ 2
1297
+ ];
1298
+ }
1299
+ });
1300
+ }).call(_this1);
1301
+ };
1302
+ return _object_spread_props(_object_spread({}, module), {
1303
+ handler: wrappedHandler
1304
+ });
1305
+ };
1306
+ return {
1307
+ // Use structural constraints to avoid contravariance check on handler type.
1308
+ // wrapAtPosition is now generic and returns T directly.
1309
+ withToolAuth: function(module) {
1310
+ return wrapAtPosition(module, 1);
1311
+ },
1312
+ withResourceAuth: function(module) {
1313
+ return wrapAtPosition(module, 2);
1314
+ },
1315
+ withPromptAuth: function(module) {
1316
+ return wrapAtPosition(module, 0);
1317
+ }
1318
+ };
1319
+ };
1320
+ return LoopbackOAuthProvider;
1321
+ }();
1322
+ function createMicrosoftFileAuth(config) {
1323
+ return new LoopbackOAuthProvider(config);
1324
+ }
1325
+ /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }