@mcp-z/oauth-google 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 +93 -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 +1189 -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 +107 -0
  29. package/dist/cjs/providers/dcr.d.ts +107 -0
  30. package/dist/cjs/providers/dcr.js +584 -0
  31. package/dist/cjs/providers/dcr.js.map +1 -0
  32. package/dist/cjs/providers/loopback-oauth.d.cts +119 -0
  33. package/dist/cjs/providers/loopback-oauth.d.ts +119 -0
  34. package/dist/cjs/providers/loopback-oauth.js +1334 -0
  35. package/dist/cjs/providers/loopback-oauth.js.map +1 -0
  36. package/dist/cjs/providers/service-account.d.cts +131 -0
  37. package/dist/cjs/providers/service-account.d.ts +131 -0
  38. package/dist/cjs/providers/service-account.js +800 -0
  39. package/dist/cjs/providers/service-account.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 +112 -0
  45. package/dist/cjs/setup/config.d.ts +112 -0
  46. package/dist/cjs/setup/config.js +236 -0
  47. package/dist/cjs/setup/config.js.map +1 -0
  48. package/dist/cjs/types.d.cts +173 -0
  49. package/dist/cjs/types.d.ts +173 -0
  50. package/dist/cjs/types.js +16 -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 +515 -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 +107 -0
  72. package/dist/esm/providers/dcr.js +242 -0
  73. package/dist/esm/providers/dcr.js.map +1 -0
  74. package/dist/esm/providers/loopback-oauth.d.ts +119 -0
  75. package/dist/esm/providers/loopback-oauth.js +639 -0
  76. package/dist/esm/providers/loopback-oauth.js.map +1 -0
  77. package/dist/esm/providers/service-account.d.ts +131 -0
  78. package/dist/esm/providers/service-account.js +353 -0
  79. package/dist/esm/providers/service-account.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 +112 -0
  84. package/dist/esm/setup/config.js +258 -0
  85. package/dist/esm/setup/config.js.map +1 -0
  86. package/dist/esm/types.d.ts +173 -0
  87. package/dist/esm/types.js +6 -0
  88. package/dist/esm/types.js.map +1 -0
  89. package/package.json +89 -0
@@ -0,0 +1,800 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "ServiceAccountProvider", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return ServiceAccountProvider;
9
+ }
10
+ });
11
+ var _fs = require("fs");
12
+ var _googleauthlibrary = require("google-auth-library");
13
+ var _jose = require("jose");
14
+ function _array_like_to_array(arr, len) {
15
+ if (len == null || len > arr.length) len = arr.length;
16
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
17
+ return arr2;
18
+ }
19
+ function _array_without_holes(arr) {
20
+ if (Array.isArray(arr)) return _array_like_to_array(arr);
21
+ }
22
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
23
+ try {
24
+ var info = gen[key](arg);
25
+ var value = info.value;
26
+ } catch (error) {
27
+ reject(error);
28
+ return;
29
+ }
30
+ if (info.done) {
31
+ resolve(value);
32
+ } else {
33
+ Promise.resolve(value).then(_next, _throw);
34
+ }
35
+ }
36
+ function _async_to_generator(fn) {
37
+ return function() {
38
+ var self = this, args = arguments;
39
+ return new Promise(function(resolve, reject) {
40
+ var gen = fn.apply(self, args);
41
+ function _next(value) {
42
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
43
+ }
44
+ function _throw(err) {
45
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
46
+ }
47
+ _next(undefined);
48
+ });
49
+ };
50
+ }
51
+ function _class_call_check(instance, Constructor) {
52
+ if (!(instance instanceof Constructor)) {
53
+ throw new TypeError("Cannot call a class as a function");
54
+ }
55
+ }
56
+ function _define_property(obj, key, value) {
57
+ if (key in obj) {
58
+ Object.defineProperty(obj, key, {
59
+ value: value,
60
+ enumerable: true,
61
+ configurable: true,
62
+ writable: true
63
+ });
64
+ } else {
65
+ obj[key] = value;
66
+ }
67
+ return obj;
68
+ }
69
+ function _instanceof(left, right) {
70
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
71
+ return !!right[Symbol.hasInstance](left);
72
+ } else {
73
+ return left instanceof right;
74
+ }
75
+ }
76
+ function _iterable_to_array(iter) {
77
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
78
+ }
79
+ function _non_iterable_spread() {
80
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
81
+ }
82
+ function _object_spread(target) {
83
+ for(var i = 1; i < arguments.length; i++){
84
+ var source = arguments[i] != null ? arguments[i] : {};
85
+ var ownKeys = Object.keys(source);
86
+ if (typeof Object.getOwnPropertySymbols === "function") {
87
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
88
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
89
+ }));
90
+ }
91
+ ownKeys.forEach(function(key) {
92
+ _define_property(target, key, source[key]);
93
+ });
94
+ }
95
+ return target;
96
+ }
97
+ function ownKeys(object, enumerableOnly) {
98
+ var keys = Object.keys(object);
99
+ if (Object.getOwnPropertySymbols) {
100
+ var symbols = Object.getOwnPropertySymbols(object);
101
+ if (enumerableOnly) {
102
+ symbols = symbols.filter(function(sym) {
103
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
104
+ });
105
+ }
106
+ keys.push.apply(keys, symbols);
107
+ }
108
+ return keys;
109
+ }
110
+ function _object_spread_props(target, source) {
111
+ source = source != null ? source : {};
112
+ if (Object.getOwnPropertyDescriptors) {
113
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
114
+ } else {
115
+ ownKeys(Object(source)).forEach(function(key) {
116
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
117
+ });
118
+ }
119
+ return target;
120
+ }
121
+ function _to_consumable_array(arr) {
122
+ return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
123
+ }
124
+ function _type_of(obj) {
125
+ "@swc/helpers - typeof";
126
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
127
+ }
128
+ function _unsupported_iterable_to_array(o, minLen) {
129
+ if (!o) return;
130
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
131
+ var n = Object.prototype.toString.call(o).slice(8, -1);
132
+ if (n === "Object" && o.constructor) n = o.constructor.name;
133
+ if (n === "Map" || n === "Set") return Array.from(n);
134
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
135
+ }
136
+ function _ts_generator(thisArg, body) {
137
+ var f, y, t, _ = {
138
+ label: 0,
139
+ sent: function() {
140
+ if (t[0] & 1) throw t[1];
141
+ return t[1];
142
+ },
143
+ trys: [],
144
+ ops: []
145
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
146
+ return d(g, "next", {
147
+ value: verb(0)
148
+ }), d(g, "throw", {
149
+ value: verb(1)
150
+ }), d(g, "return", {
151
+ value: verb(2)
152
+ }), typeof Symbol === "function" && d(g, Symbol.iterator, {
153
+ value: function() {
154
+ return this;
155
+ }
156
+ }), g;
157
+ function verb(n) {
158
+ return function(v) {
159
+ return step([
160
+ n,
161
+ v
162
+ ]);
163
+ };
164
+ }
165
+ function step(op) {
166
+ if (f) throw new TypeError("Generator is already executing.");
167
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
168
+ 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;
169
+ if (y = 0, t) op = [
170
+ op[0] & 2,
171
+ t.value
172
+ ];
173
+ switch(op[0]){
174
+ case 0:
175
+ case 1:
176
+ t = op;
177
+ break;
178
+ case 4:
179
+ _.label++;
180
+ return {
181
+ value: op[1],
182
+ done: false
183
+ };
184
+ case 5:
185
+ _.label++;
186
+ y = op[1];
187
+ op = [
188
+ 0
189
+ ];
190
+ continue;
191
+ case 7:
192
+ op = _.ops.pop();
193
+ _.trys.pop();
194
+ continue;
195
+ default:
196
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
197
+ _ = 0;
198
+ continue;
199
+ }
200
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
201
+ _.label = op[1];
202
+ break;
203
+ }
204
+ if (op[0] === 6 && _.label < t[1]) {
205
+ _.label = t[1];
206
+ t = op;
207
+ break;
208
+ }
209
+ if (t && _.label < t[2]) {
210
+ _.label = t[2];
211
+ _.ops.push(op);
212
+ break;
213
+ }
214
+ if (t[2]) _.ops.pop();
215
+ _.trys.pop();
216
+ continue;
217
+ }
218
+ op = body.call(thisArg, _);
219
+ } catch (e) {
220
+ op = [
221
+ 6,
222
+ e
223
+ ];
224
+ y = 0;
225
+ } finally{
226
+ f = t = 0;
227
+ }
228
+ if (op[0] & 5) throw op[1];
229
+ return {
230
+ value: op[0] ? op[1] : void 0,
231
+ done: true
232
+ };
233
+ }
234
+ }
235
+ var ServiceAccountProvider = /*#__PURE__*/ function() {
236
+ "use strict";
237
+ function ServiceAccountProvider(config) {
238
+ _class_call_check(this, ServiceAccountProvider);
239
+ this.config = config;
240
+ this.keyFilePath = config.keyFilePath;
241
+ this.scopes = config.scopes;
242
+ }
243
+ var _proto = ServiceAccountProvider.prototype;
244
+ /**
245
+ * Load and parse service account key file from disk
246
+ * Validates structure and caches for subsequent calls
247
+ */ _proto.loadKeyFile = function loadKeyFile() {
248
+ return _async_to_generator(function() {
249
+ var fileContent, keyData, error;
250
+ return _ts_generator(this, function(_state) {
251
+ switch(_state.label){
252
+ case 0:
253
+ // Return cached key data if already loaded
254
+ if (this.keyData) {
255
+ return [
256
+ 2,
257
+ this.keyData
258
+ ];
259
+ }
260
+ _state.label = 1;
261
+ case 1:
262
+ _state.trys.push([
263
+ 1,
264
+ 3,
265
+ ,
266
+ 4
267
+ ]);
268
+ return [
269
+ 4,
270
+ _fs.promises.readFile(this.keyFilePath, 'utf-8')
271
+ ];
272
+ case 2:
273
+ fileContent = _state.sent();
274
+ try {
275
+ keyData = JSON.parse(fileContent);
276
+ } catch (parseError) {
277
+ throw new Error("Failed to parse service account key file as JSON: ".concat(this.keyFilePath, "\n") + "Error: ".concat(_instanceof(parseError, Error) ? parseError.message : String(parseError)));
278
+ }
279
+ // Validate structure
280
+ this.keyData = this.validateKeyFile(keyData);
281
+ return [
282
+ 2,
283
+ this.keyData
284
+ ];
285
+ case 3:
286
+ error = _state.sent();
287
+ // Handle file not found
288
+ if (error.code === 'ENOENT') {
289
+ throw new Error("Service account key file not found: ".concat(this.keyFilePath, "\nMake sure GOOGLE_SERVICE_ACCOUNT_KEY_FILE points to a valid file path."));
290
+ }
291
+ // Handle permission errors
292
+ if (error.code === 'EACCES') {
293
+ throw new Error("Permission denied reading service account key file: ".concat(this.keyFilePath, "\nCheck file permissions (should be readable by current user)."));
294
+ }
295
+ // Re-throw other errors
296
+ throw error;
297
+ case 4:
298
+ return [
299
+ 2
300
+ ];
301
+ }
302
+ });
303
+ }).call(this);
304
+ };
305
+ /**
306
+ * Validate service account key file structure
307
+ * Ensures all required fields are present and correctly typed
308
+ */ _proto.validateKeyFile = function validateKeyFile(data) {
309
+ if (!data || (typeof data === "undefined" ? "undefined" : _type_of(data)) !== 'object') {
310
+ throw new Error('Service account key file must contain a JSON object');
311
+ }
312
+ var obj = data;
313
+ // Validate type field
314
+ if (obj.type !== 'service_account') {
315
+ throw new Error('Invalid service account key file: Expected type "service_account", got "'.concat(obj.type, '"\nMake sure you downloaded a service account key, not an OAuth client credential.'));
316
+ }
317
+ // Validate required string fields
318
+ var requiredFields = [
319
+ 'project_id',
320
+ 'private_key_id',
321
+ 'private_key',
322
+ 'client_email',
323
+ 'client_id',
324
+ 'auth_uri',
325
+ 'token_uri'
326
+ ];
327
+ var missingFields = requiredFields.filter(function(field) {
328
+ return typeof obj[field] !== 'string' || !obj[field];
329
+ });
330
+ if (missingFields.length > 0) {
331
+ throw new Error("Service account key file is missing required fields: ".concat(missingFields.join(', '), "\nMake sure you downloaded a complete service account key file from Google Cloud Console."));
332
+ }
333
+ // Validate private key format
334
+ var privateKey = obj.private_key;
335
+ if (!privateKey.includes('BEGIN PRIVATE KEY') || !privateKey.includes('END PRIVATE KEY')) {
336
+ throw new Error('Service account private_key field does not contain a valid PEM-formatted key.\n' + 'Expected format: -----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----');
337
+ }
338
+ return obj;
339
+ };
340
+ /**
341
+ * Generate signed JWT (JSON Web Token) for service account authentication
342
+ * Uses RS256 algorithm with private key from key file
343
+ */ _proto.generateJWT = function generateJWT() {
344
+ return _async_to_generator(function() {
345
+ var keyData, privateKey, now, jwt;
346
+ return _ts_generator(this, function(_state) {
347
+ switch(_state.label){
348
+ case 0:
349
+ return [
350
+ 4,
351
+ this.loadKeyFile()
352
+ ];
353
+ case 1:
354
+ keyData = _state.sent();
355
+ return [
356
+ 4,
357
+ (0, _jose.importPKCS8)(keyData.private_key, 'RS256')
358
+ ];
359
+ case 2:
360
+ privateKey = _state.sent();
361
+ // Current time
362
+ now = Math.floor(Date.now() / 1000);
363
+ return [
364
+ 4,
365
+ new _jose.SignJWT({
366
+ iss: keyData.client_email,
367
+ scope: this.scopes.join(' '),
368
+ aud: 'https://oauth2.googleapis.com/token',
369
+ exp: now + 3600,
370
+ iat: now
371
+ }).setProtectedHeader({
372
+ alg: 'RS256',
373
+ typ: 'JWT'
374
+ }).sign(privateKey)
375
+ ];
376
+ case 3:
377
+ jwt = _state.sent();
378
+ return [
379
+ 2,
380
+ jwt
381
+ ];
382
+ }
383
+ });
384
+ }).call(this);
385
+ };
386
+ /**
387
+ * Exchange signed JWT for access token at Google OAuth endpoint
388
+ * POST to https://oauth2.googleapis.com/token with grant_type=jwt-bearer
389
+ */ _proto.exchangeJWT = function exchangeJWT(jwt) {
390
+ return _async_to_generator(function() {
391
+ var tokenEndpoint, response, errorText, errorMessage, errorJson, tokenData, expiry, error;
392
+ return _ts_generator(this, function(_state) {
393
+ switch(_state.label){
394
+ case 0:
395
+ tokenEndpoint = 'https://oauth2.googleapis.com/token';
396
+ _state.label = 1;
397
+ case 1:
398
+ _state.trys.push([
399
+ 1,
400
+ 6,
401
+ ,
402
+ 7
403
+ ]);
404
+ return [
405
+ 4,
406
+ fetch(tokenEndpoint, {
407
+ method: 'POST',
408
+ headers: {
409
+ 'Content-Type': 'application/x-www-form-urlencoded'
410
+ },
411
+ body: new URLSearchParams({
412
+ grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
413
+ assertion: jwt
414
+ })
415
+ })
416
+ ];
417
+ case 2:
418
+ response = _state.sent();
419
+ if (!!response.ok) return [
420
+ 3,
421
+ 4
422
+ ];
423
+ return [
424
+ 4,
425
+ response.text()
426
+ ];
427
+ case 3:
428
+ errorText = _state.sent();
429
+ try {
430
+ errorJson = JSON.parse(errorText);
431
+ errorMessage = errorJson.error_description || errorJson.error || errorText;
432
+ } catch (unused) {
433
+ errorMessage = errorText;
434
+ }
435
+ // 400: Invalid JWT (malformed claims, expired, etc.)
436
+ if (response.status === 400) {
437
+ throw new Error("Invalid service account JWT: ".concat(errorMessage, "\nThis usually means the JWT claims are malformed or the key file is invalid."));
438
+ }
439
+ // 401: Unauthorized (revoked service account, wrong scopes, etc.)
440
+ if (response.status === 401) {
441
+ throw new Error("Service account authentication failed: ".concat(errorMessage, "\nThe service account may have been disabled or deleted. Check Google Cloud Console."));
442
+ }
443
+ // Other errors
444
+ throw new Error("Token exchange failed (HTTP ".concat(response.status, "): ").concat(errorMessage));
445
+ case 4:
446
+ return [
447
+ 4,
448
+ response.json()
449
+ ];
450
+ case 5:
451
+ tokenData = _state.sent();
452
+ // Calculate expiry timestamp (token expires in ~1 hour)
453
+ expiry = Date.now() + (tokenData.expires_in - 60) * 1000; // Subtract 60s for safety margin
454
+ return [
455
+ 2,
456
+ {
457
+ token: tokenData.access_token,
458
+ expiry: expiry
459
+ }
460
+ ];
461
+ case 6:
462
+ error = _state.sent();
463
+ // Network errors
464
+ if (_instanceof(error, TypeError) && error.message.includes('fetch')) {
465
+ throw new Error('Network error connecting to Google OAuth endpoint. Check internet connection.');
466
+ }
467
+ // Re-throw other errors
468
+ throw error;
469
+ case 7:
470
+ return [
471
+ 2
472
+ ];
473
+ }
474
+ });
475
+ })();
476
+ };
477
+ /**
478
+ * Get access token for Google APIs
479
+ * Generates fresh JWT and exchanges for access token on each call
480
+ *
481
+ * Note: accountId parameter is ignored for service accounts (service account is single static identity)
482
+ */ _proto.getAccessToken = function getAccessToken(_accountId) {
483
+ return _async_to_generator(function() {
484
+ var jwt, _ref, token, expiry, error;
485
+ return _ts_generator(this, function(_state) {
486
+ switch(_state.label){
487
+ case 0:
488
+ // Check if we have a valid cached token (optional optimization)
489
+ if (this.cachedToken && this.cachedToken.expiry > Date.now()) {
490
+ return [
491
+ 2,
492
+ this.cachedToken.token
493
+ ];
494
+ }
495
+ _state.label = 1;
496
+ case 1:
497
+ _state.trys.push([
498
+ 1,
499
+ 4,
500
+ ,
501
+ 5
502
+ ]);
503
+ return [
504
+ 4,
505
+ this.generateJWT()
506
+ ];
507
+ case 2:
508
+ jwt = _state.sent();
509
+ return [
510
+ 4,
511
+ this.exchangeJWT(jwt)
512
+ ];
513
+ case 3:
514
+ _ref = _state.sent(), token = _ref.token, expiry = _ref.expiry;
515
+ // Cache token for subsequent calls (optional optimization)
516
+ this.cachedToken = {
517
+ token: token,
518
+ expiry: expiry
519
+ };
520
+ return [
521
+ 2,
522
+ token
523
+ ];
524
+ case 4:
525
+ error = _state.sent();
526
+ // Add context to errors
527
+ throw new Error("Failed to get service account access token: ".concat(_instanceof(error, Error) ? error.message : String(error)));
528
+ case 5:
529
+ return [
530
+ 2
531
+ ];
532
+ }
533
+ });
534
+ }).call(this);
535
+ };
536
+ /**
537
+ * Get OAuth2Client with service account credentials for googleapis
538
+ * This is the CRITICAL method that servers use to get authenticated API clients
539
+ *
540
+ * Service account ONLY works with accountId='service-account' (single static identity)
541
+ *
542
+ @param accountId - Account identifier (must be 'service-account' or undefined)
543
+ * @returns OAuth2Client instance with access token credentials set
544
+ */ _proto.toAuth = function toAuth(accountId) {
545
+ var _this = this;
546
+ var _this_config_logger;
547
+ // Service account ONLY works with 'service-account' account ID
548
+ if (accountId !== undefined && accountId !== 'service-account') {
549
+ throw new Error("ServiceAccountProvider only supports accountId='service-account', got '".concat(accountId, "'. Service account uses a single static identity pattern."));
550
+ }
551
+ // Create OAuth2Client instance (no client ID/secret needed for service accounts)
552
+ var client = new _googleauthlibrary.OAuth2Client();
553
+ // Override getRequestMetadataAsync to provide authentication headers for each request
554
+ // This is the method googleapis calls to get auth headers - can be async and fetch tokens on-demand
555
+ client.getRequestMetadataAsync = function(_url) {
556
+ return _async_to_generator(function() {
557
+ var token, headers, error, _this_config_logger;
558
+ return _ts_generator(this, function(_state) {
559
+ switch(_state.label){
560
+ case 0:
561
+ _state.trys.push([
562
+ 0,
563
+ 2,
564
+ ,
565
+ 3
566
+ ]);
567
+ return [
568
+ 4,
569
+ this.getAccessToken()
570
+ ];
571
+ case 1:
572
+ token = _state.sent();
573
+ // Update client credentials for consistency (other googleapis methods might check these)
574
+ client.credentials = {
575
+ access_token: token,
576
+ token_type: 'Bearer'
577
+ };
578
+ // Return headers as Headers instance for proper TypeScript types
579
+ headers = new Headers();
580
+ headers.set('authorization', "Bearer ".concat(token));
581
+ return [
582
+ 2,
583
+ {
584
+ headers: headers
585
+ }
586
+ ];
587
+ case 2:
588
+ error = _state.sent();
589
+ (_this_config_logger = this.config.logger) === null || _this_config_logger === void 0 ? void 0 : _this_config_logger.error('Failed to get service account access token for API request', {
590
+ error: error
591
+ });
592
+ throw error;
593
+ case 3:
594
+ return [
595
+ 2
596
+ ];
597
+ }
598
+ });
599
+ }).call(_this);
600
+ };
601
+ // Override getAccessToken to support googleapis client API and direct token access
602
+ client.getAccessToken = function() {
603
+ return _async_to_generator(function() {
604
+ var token, error, _this_config_logger;
605
+ return _ts_generator(this, function(_state) {
606
+ switch(_state.label){
607
+ case 0:
608
+ _state.trys.push([
609
+ 0,
610
+ 2,
611
+ ,
612
+ 3
613
+ ]);
614
+ return [
615
+ 4,
616
+ this.getAccessToken()
617
+ ];
618
+ case 1:
619
+ token = _state.sent();
620
+ return [
621
+ 2,
622
+ {
623
+ token: token
624
+ }
625
+ ];
626
+ case 2:
627
+ error = _state.sent();
628
+ (_this_config_logger = this.config.logger) === null || _this_config_logger === void 0 ? void 0 : _this_config_logger.error('Failed to get service account access token', {
629
+ error: error
630
+ });
631
+ throw error;
632
+ case 3:
633
+ return [
634
+ 2
635
+ ];
636
+ }
637
+ });
638
+ }).call(_this);
639
+ };
640
+ (_this_config_logger = this.config.logger) === null || _this_config_logger === void 0 ? void 0 : _this_config_logger.debug("ServiceAccountProvider: OAuth2Client created for ".concat(accountId));
641
+ return client;
642
+ };
643
+ /**
644
+ * Get service account email address
645
+ * Used for account registration and display
646
+ *
647
+ * Note: accountId parameter is ignored for service accounts
648
+ * @returns Service account email from key file (e.g., "service-account@project.iam.gserviceaccount.com")
649
+ */ _proto.getUserEmail = function getUserEmail(_accountId) {
650
+ return _async_to_generator(function() {
651
+ var keyData;
652
+ return _ts_generator(this, function(_state) {
653
+ switch(_state.label){
654
+ case 0:
655
+ return [
656
+ 4,
657
+ this.loadKeyFile()
658
+ ];
659
+ case 1:
660
+ keyData = _state.sent();
661
+ return [
662
+ 2,
663
+ keyData.client_email
664
+ ];
665
+ }
666
+ });
667
+ }).call(this);
668
+ };
669
+ /**
670
+ * Create middleware wrapper for single-user authentication
671
+ * This is the CRITICAL method that integrates service account auth into MCP servers
672
+ *
673
+ * Middleware wraps tool, resource, and prompt handlers and injects authContext into extra parameter.
674
+ * Handlers receive OAuth2Client via extra.authContext.auth for API calls.
675
+ *
676
+ * @returns Object with withToolAuth, withResourceAuth, withPromptAuth methods
677
+ *
678
+ * @example
679
+ * ```typescript
680
+ * // Server registration
681
+ * const authMiddleware = provider.authMiddleware();
682
+ * const tools = toolFactories.map(f => f()).map(authMiddleware.withToolAuth);
683
+ * const resources = resourceFactories.map(f => f()).map(authMiddleware.withResourceAuth);
684
+ * const prompts = promptFactories.map(f => f()).map(authMiddleware.withPromptAuth);
685
+ *
686
+ * // Tool handler receives auth
687
+ * async function handler({ id }: In, extra: EnrichedExtra) {
688
+ * // extra.authContext.auth is OAuth2Client (from middleware)
689
+ * const gmail = google.gmail({ version: 'v1', auth: extra.authContext.auth });
690
+ * }
691
+ * ```
692
+ */ _proto.authMiddleware = function authMiddleware() {
693
+ var _this = this;
694
+ // Shared wrapper logic - extracts extra parameter from specified position
695
+ // Generic T captures the actual module type; handler is cast from unknown to callable
696
+ var wrapAtPosition = function(module, extraPosition) {
697
+ var _this1 = _this;
698
+ var originalHandler = module.handler;
699
+ var wrappedHandler = function() {
700
+ for(var _len = arguments.length, allArgs = new Array(_len), _key = 0; _key < _len; _key++){
701
+ allArgs[_key] = arguments[_key];
702
+ }
703
+ return _async_to_generator(function() {
704
+ var extra, accountId, serviceEmail, auth, error, message;
705
+ return _ts_generator(this, function(_state) {
706
+ switch(_state.label){
707
+ case 0:
708
+ // Extract extra from the correct position
709
+ extra = allArgs[extraPosition];
710
+ _state.label = 1;
711
+ case 1:
712
+ _state.trys.push([
713
+ 1,
714
+ 5,
715
+ ,
716
+ 6
717
+ ]);
718
+ // Use fixed accountId for storage isolation (like device-code pattern)
719
+ accountId = 'service-account';
720
+ return [
721
+ 4,
722
+ this.getUserEmail()
723
+ ];
724
+ case 2:
725
+ serviceEmail = _state.sent();
726
+ // Get access token (generates JWT and exchanges if needed)
727
+ return [
728
+ 4,
729
+ this.getAccessToken()
730
+ ];
731
+ case 3:
732
+ _state.sent();
733
+ // Create OAuth2Client with service account credentials
734
+ auth = this.toAuth(accountId);
735
+ // Inject authContext and logger into extra parameter
736
+ extra.authContext = {
737
+ auth: auth,
738
+ accountId: accountId,
739
+ metadata: {
740
+ serviceEmail: serviceEmail
741
+ }
742
+ };
743
+ extra.logger = this.config.logger;
744
+ return [
745
+ 4,
746
+ originalHandler.apply(void 0, _to_consumable_array(allArgs))
747
+ ];
748
+ case 4:
749
+ // Call original handler with all args
750
+ return [
751
+ 2,
752
+ _state.sent()
753
+ ];
754
+ case 5:
755
+ error = _state.sent();
756
+ message = _instanceof(error, Error) ? error.message : String(error);
757
+ // Provide specific, actionable error messages based on error type
758
+ if (message.includes('key file not found')) {
759
+ throw new Error("Service account setup error: Key file '".concat(this.keyFilePath, "' not found.\n• Set GOOGLE_SERVICE_ACCOUNT_KEY_FILE environment variable\n• Or ensure the file path exists and is accessible"));
760
+ }
761
+ if (message.includes('Forbidden') || message.includes('access_denied')) {
762
+ throw new Error('Service account permission error: The service account does not have required permissions.\n' + '• Ensure the service account has been granted the necessary roles\n' + '• Check that required API scopes are enabled in Google Cloud Console\n' + '• Verify the service account is active (not disabled)');
763
+ }
764
+ if (message.includes('invalid_grant') || message.includes('JWT')) {
765
+ throw new Error('Service account authentication error: Invalid credentials or expired tokens.\n' + '• Verify your service account key file is valid and not expired\n' + '• Check that the service account email and project match your GCP setup\n' + '• Try regenerating the key file in Google Cloud Console');
766
+ }
767
+ if (message.includes('Network error') || message.includes('fetch')) {
768
+ throw new Error('Service account connection error: Unable to reach Google authentication services.\n' + '• Check your internet connection\n' + '• Verify firewall/proxy settings allow HTTPS to oauth2.googleapis.com\n' + '• Try again in a few moments (may be temporary service issue)');
769
+ }
770
+ // Generic fallback with original error
771
+ throw new Error("Service account authentication failed: ".concat(message));
772
+ case 6:
773
+ return [
774
+ 2
775
+ ];
776
+ }
777
+ });
778
+ }).call(_this1);
779
+ };
780
+ return _object_spread_props(_object_spread({}, module), {
781
+ handler: wrappedHandler
782
+ });
783
+ };
784
+ return {
785
+ // Use structural constraints to avoid contravariance check on handler type.
786
+ // wrapAtPosition is now generic and returns T directly.
787
+ withToolAuth: function(module) {
788
+ return wrapAtPosition(module, 1);
789
+ },
790
+ withResourceAuth: function(module) {
791
+ return wrapAtPosition(module, 2);
792
+ },
793
+ withPromptAuth: function(module) {
794
+ return wrapAtPosition(module, 0);
795
+ }
796
+ };
797
+ };
798
+ return ServiceAccountProvider;
799
+ }();
800
+ /* 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; }