@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,584 @@
1
+ /**
2
+ * DCR Provider - Stateless Dynamic Client Registration Provider
3
+ *
4
+ * Implements stateless provider pattern where provider tokens are received from
5
+ * token verification context rather than managed by the provider itself.
6
+ *
7
+ * Use case: MCP HTTP servers with DCR authentication where client manages tokens
8
+ * and provider only handles Google API calls with provided credentials.
9
+ */ "use strict";
10
+ Object.defineProperty(exports, "__esModule", {
11
+ value: true
12
+ });
13
+ Object.defineProperty(exports, "DcrOAuthProvider", {
14
+ enumerable: true,
15
+ get: function() {
16
+ return DcrOAuthProvider;
17
+ }
18
+ });
19
+ var _types = require("@modelcontextprotocol/sdk/types.js");
20
+ var _googleauthlibrary = require("google-auth-library");
21
+ function _array_like_to_array(arr, len) {
22
+ if (len == null || len > arr.length) len = arr.length;
23
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
24
+ return arr2;
25
+ }
26
+ function _array_without_holes(arr) {
27
+ if (Array.isArray(arr)) return _array_like_to_array(arr);
28
+ }
29
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
30
+ try {
31
+ var info = gen[key](arg);
32
+ var value = info.value;
33
+ } catch (error) {
34
+ reject(error);
35
+ return;
36
+ }
37
+ if (info.done) {
38
+ resolve(value);
39
+ } else {
40
+ Promise.resolve(value).then(_next, _throw);
41
+ }
42
+ }
43
+ function _async_to_generator(fn) {
44
+ return function() {
45
+ var self = this, args = arguments;
46
+ return new Promise(function(resolve, reject) {
47
+ var gen = fn.apply(self, args);
48
+ function _next(value) {
49
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
50
+ }
51
+ function _throw(err) {
52
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
53
+ }
54
+ _next(undefined);
55
+ });
56
+ };
57
+ }
58
+ function _class_call_check(instance, Constructor) {
59
+ if (!(instance instanceof Constructor)) {
60
+ throw new TypeError("Cannot call a class as a function");
61
+ }
62
+ }
63
+ function _define_property(obj, key, value) {
64
+ if (key in obj) {
65
+ Object.defineProperty(obj, key, {
66
+ value: value,
67
+ enumerable: true,
68
+ configurable: true,
69
+ writable: true
70
+ });
71
+ } else {
72
+ obj[key] = value;
73
+ }
74
+ return obj;
75
+ }
76
+ function _instanceof(left, right) {
77
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
78
+ return !!right[Symbol.hasInstance](left);
79
+ } else {
80
+ return left instanceof right;
81
+ }
82
+ }
83
+ function _iterable_to_array(iter) {
84
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
85
+ }
86
+ function _non_iterable_spread() {
87
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
88
+ }
89
+ function _object_spread(target) {
90
+ for(var i = 1; i < arguments.length; i++){
91
+ var source = arguments[i] != null ? arguments[i] : {};
92
+ var ownKeys = Object.keys(source);
93
+ if (typeof Object.getOwnPropertySymbols === "function") {
94
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
95
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
96
+ }));
97
+ }
98
+ ownKeys.forEach(function(key) {
99
+ _define_property(target, key, source[key]);
100
+ });
101
+ }
102
+ return target;
103
+ }
104
+ function ownKeys(object, enumerableOnly) {
105
+ var keys = Object.keys(object);
106
+ if (Object.getOwnPropertySymbols) {
107
+ var symbols = Object.getOwnPropertySymbols(object);
108
+ if (enumerableOnly) {
109
+ symbols = symbols.filter(function(sym) {
110
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
111
+ });
112
+ }
113
+ keys.push.apply(keys, symbols);
114
+ }
115
+ return keys;
116
+ }
117
+ function _object_spread_props(target, source) {
118
+ source = source != null ? source : {};
119
+ if (Object.getOwnPropertyDescriptors) {
120
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
121
+ } else {
122
+ ownKeys(Object(source)).forEach(function(key) {
123
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
124
+ });
125
+ }
126
+ return target;
127
+ }
128
+ function _to_consumable_array(arr) {
129
+ return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
130
+ }
131
+ function _type_of(obj) {
132
+ "@swc/helpers - typeof";
133
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
134
+ }
135
+ function _unsupported_iterable_to_array(o, minLen) {
136
+ if (!o) return;
137
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
138
+ var n = Object.prototype.toString.call(o).slice(8, -1);
139
+ if (n === "Object" && o.constructor) n = o.constructor.name;
140
+ if (n === "Map" || n === "Set") return Array.from(n);
141
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
142
+ }
143
+ function _ts_generator(thisArg, body) {
144
+ var f, y, t, _ = {
145
+ label: 0,
146
+ sent: function() {
147
+ if (t[0] & 1) throw t[1];
148
+ return t[1];
149
+ },
150
+ trys: [],
151
+ ops: []
152
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
153
+ return d(g, "next", {
154
+ value: verb(0)
155
+ }), d(g, "throw", {
156
+ value: verb(1)
157
+ }), d(g, "return", {
158
+ value: verb(2)
159
+ }), typeof Symbol === "function" && d(g, Symbol.iterator, {
160
+ value: function() {
161
+ return this;
162
+ }
163
+ }), g;
164
+ function verb(n) {
165
+ return function(v) {
166
+ return step([
167
+ n,
168
+ v
169
+ ]);
170
+ };
171
+ }
172
+ function step(op) {
173
+ if (f) throw new TypeError("Generator is already executing.");
174
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
175
+ 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;
176
+ if (y = 0, t) op = [
177
+ op[0] & 2,
178
+ t.value
179
+ ];
180
+ switch(op[0]){
181
+ case 0:
182
+ case 1:
183
+ t = op;
184
+ break;
185
+ case 4:
186
+ _.label++;
187
+ return {
188
+ value: op[1],
189
+ done: false
190
+ };
191
+ case 5:
192
+ _.label++;
193
+ y = op[1];
194
+ op = [
195
+ 0
196
+ ];
197
+ continue;
198
+ case 7:
199
+ op = _.ops.pop();
200
+ _.trys.pop();
201
+ continue;
202
+ default:
203
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
204
+ _ = 0;
205
+ continue;
206
+ }
207
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
208
+ _.label = op[1];
209
+ break;
210
+ }
211
+ if (op[0] === 6 && _.label < t[1]) {
212
+ _.label = t[1];
213
+ t = op;
214
+ break;
215
+ }
216
+ if (t && _.label < t[2]) {
217
+ _.label = t[2];
218
+ _.ops.push(op);
219
+ break;
220
+ }
221
+ if (t[2]) _.ops.pop();
222
+ _.trys.pop();
223
+ continue;
224
+ }
225
+ op = body.call(thisArg, _);
226
+ } catch (e) {
227
+ op = [
228
+ 6,
229
+ e
230
+ ];
231
+ y = 0;
232
+ } finally{
233
+ f = t = 0;
234
+ }
235
+ if (op[0] & 5) throw op[1];
236
+ return {
237
+ value: op[0] ? op[1] : void 0,
238
+ done: true
239
+ };
240
+ }
241
+ }
242
+ var DcrOAuthProvider = /*#__PURE__*/ function() {
243
+ "use strict";
244
+ function DcrOAuthProvider(config) {
245
+ _class_call_check(this, DcrOAuthProvider);
246
+ this.emailCache = new Map();
247
+ this.config = config;
248
+ }
249
+ var _proto = DcrOAuthProvider.prototype;
250
+ /**
251
+ * Create Google OAuth2Client from provider tokens
252
+ *
253
+ * This is the core stateless pattern - provider receives tokens from context
254
+ * (token verification, HTTP request) and creates OAuth2Client on-demand.
255
+ *
256
+ * @param tokens - Provider tokens (Google access/refresh tokens)
257
+ * @returns Google OAuth2Client configured with credentials
258
+ */ _proto.toAuth = function toAuth(tokens) {
259
+ var _this = this;
260
+ var _tokens_refreshToken, _tokens_expiresAt;
261
+ var _this_config = this.config, clientId = _this_config.clientId, clientSecret = _this_config.clientSecret;
262
+ // Create OAuth2Client with credentials
263
+ var client = new _googleauthlibrary.OAuth2Client(_object_spread({
264
+ clientId: clientId
265
+ }, clientSecret && {
266
+ clientSecret: clientSecret
267
+ }));
268
+ // Set initial credentials (convert undefined to null for Google's Credentials type)
269
+ client.credentials = {
270
+ access_token: tokens.accessToken,
271
+ refresh_token: (_tokens_refreshToken = tokens.refreshToken) !== null && _tokens_refreshToken !== void 0 ? _tokens_refreshToken : null,
272
+ expiry_date: (_tokens_expiresAt = tokens.expiresAt) !== null && _tokens_expiresAt !== void 0 ? _tokens_expiresAt : null,
273
+ token_type: 'Bearer'
274
+ };
275
+ // Override getRequestMetadataAsync to handle token refresh
276
+ // @ts-expect-error - Access protected method for token refresh
277
+ var originalGetMetadata = client.getRequestMetadataAsync.bind(client);
278
+ // @ts-expect-error - Override protected method for token refresh
279
+ client.getRequestMetadataAsync = function(url) {
280
+ return _async_to_generator(function() {
281
+ var refreshedTokens, error;
282
+ return _ts_generator(this, function(_state) {
283
+ switch(_state.label){
284
+ case 0:
285
+ if (!this.needsRefresh(client.credentials.expiry_date)) return [
286
+ 3,
287
+ 4
288
+ ];
289
+ _state.label = 1;
290
+ case 1:
291
+ _state.trys.push([
292
+ 1,
293
+ 3,
294
+ ,
295
+ 4
296
+ ]);
297
+ return [
298
+ 4,
299
+ client.refreshAccessToken()
300
+ ];
301
+ case 2:
302
+ refreshedTokens = _state.sent();
303
+ client.credentials = refreshedTokens.credentials;
304
+ return [
305
+ 3,
306
+ 4
307
+ ];
308
+ case 3:
309
+ error = _state.sent();
310
+ throw new Error("Token refresh failed: ".concat(_instanceof(error, Error) ? error.message : String(error)));
311
+ case 4:
312
+ return [
313
+ 2,
314
+ originalGetMetadata(url)
315
+ ];
316
+ }
317
+ });
318
+ }).call(_this);
319
+ };
320
+ return client;
321
+ };
322
+ /**
323
+ * Check if token needs refresh (with 1 minute buffer)
324
+ */ _proto.needsRefresh = function needsRefresh(expiryDate) {
325
+ if (!expiryDate) return false; // No expiry = no refresh needed
326
+ return Date.now() >= expiryDate - 60000; // 1 minute buffer
327
+ };
328
+ /**
329
+ * Refresh Google access token using refresh token
330
+ *
331
+ * @param refreshToken - Google refresh token
332
+ * @returns New provider tokens
333
+ */ _proto.refreshAccessToken = function refreshAccessToken(refreshToken) {
334
+ return _async_to_generator(function() {
335
+ var _this_config, clientId, clientSecret, tokenUrl, params, body, response, errorText, tokenResponse, result;
336
+ return _ts_generator(this, function(_state) {
337
+ switch(_state.label){
338
+ case 0:
339
+ _this_config = this.config, clientId = _this_config.clientId, clientSecret = _this_config.clientSecret;
340
+ tokenUrl = 'https://oauth2.googleapis.com/token';
341
+ params = {
342
+ refresh_token: refreshToken,
343
+ client_id: clientId,
344
+ grant_type: 'refresh_token'
345
+ };
346
+ // Only include client_secret for confidential clients
347
+ if (clientSecret) {
348
+ params.client_secret = clientSecret;
349
+ }
350
+ body = new URLSearchParams(params);
351
+ return [
352
+ 4,
353
+ fetch(tokenUrl, {
354
+ method: 'POST',
355
+ headers: {
356
+ 'Content-Type': 'application/x-www-form-urlencoded'
357
+ },
358
+ body: body.toString()
359
+ })
360
+ ];
361
+ case 1:
362
+ response = _state.sent();
363
+ if (!!response.ok) return [
364
+ 3,
365
+ 3
366
+ ];
367
+ return [
368
+ 4,
369
+ response.text()
370
+ ];
371
+ case 2:
372
+ errorText = _state.sent();
373
+ throw new Error("Token refresh failed: ".concat(response.status, " ").concat(errorText));
374
+ case 3:
375
+ return [
376
+ 4,
377
+ response.json()
378
+ ];
379
+ case 4:
380
+ tokenResponse = _state.sent();
381
+ result = {
382
+ accessToken: tokenResponse.access_token,
383
+ refreshToken: refreshToken
384
+ };
385
+ // Only add optional fields if they have values
386
+ if (tokenResponse.expires_in !== undefined) {
387
+ result.expiresAt = Date.now() + tokenResponse.expires_in * 1000;
388
+ }
389
+ if (tokenResponse.scope !== undefined) {
390
+ result.scope = tokenResponse.scope;
391
+ }
392
+ return [
393
+ 2,
394
+ result
395
+ ];
396
+ }
397
+ });
398
+ }).call(this);
399
+ };
400
+ /**
401
+ * Get user email from Google userinfo API (with caching)
402
+ *
403
+ * @param tokens - Provider tokens to use for API call
404
+ * @returns User's email address
405
+ */ _proto.getUserEmail = function getUserEmail(tokens) {
406
+ return _async_to_generator(function() {
407
+ var _tokens_expiresAt, cacheKey, cached, auth, response, userInfo, email;
408
+ return _ts_generator(this, function(_state) {
409
+ switch(_state.label){
410
+ case 0:
411
+ cacheKey = tokens.accessToken;
412
+ cached = this.emailCache.get(cacheKey);
413
+ // Check cache (with same expiry as access token)
414
+ if (cached && Date.now() < cached.expiresAt) {
415
+ return [
416
+ 2,
417
+ cached.email
418
+ ];
419
+ }
420
+ auth = this.toAuth(tokens);
421
+ return [
422
+ 4,
423
+ auth.request({
424
+ url: 'https://www.googleapis.com/oauth2/v2/userinfo',
425
+ method: 'GET'
426
+ })
427
+ ];
428
+ case 1:
429
+ response = _state.sent();
430
+ userInfo = response.data;
431
+ email = userInfo.email;
432
+ // Cache with token expiration (default 1 hour if not specified)
433
+ this.emailCache.set(cacheKey, {
434
+ email: email,
435
+ expiresAt: (_tokens_expiresAt = tokens.expiresAt) !== null && _tokens_expiresAt !== void 0 ? _tokens_expiresAt : Date.now() + 3600000
436
+ });
437
+ return [
438
+ 2,
439
+ email
440
+ ];
441
+ }
442
+ });
443
+ }).call(this);
444
+ };
445
+ /**
446
+ * Auth middleware for HTTP servers with DCR bearer auth
447
+ * Validates bearer tokens and enriches extra with provider tokens
448
+ *
449
+ * Pattern:
450
+ * ```typescript
451
+ * const provider = new DcrOAuthProvider({ ..., verifyEndpoint: 'http://localhost:3000/oauth/verify' });
452
+ * const authMiddleware = provider.authMiddleware();
453
+ * const tools = toolFactories.map(f => f()).map(authMiddleware.withToolAuth);
454
+ * const resources = resourceFactories.map(f => f()).map(authMiddleware.withResourceAuth);
455
+ * const prompts = promptFactories.map(f => f()).map(authMiddleware.withPromptAuth);
456
+ * ```
457
+ */ _proto.authMiddleware = function authMiddleware() {
458
+ var _this = this;
459
+ // Shared wrapper logic - extracts extra parameter from specified position
460
+ // Generic T captures the actual module type; handler is cast from unknown to callable
461
+ var wrapAtPosition = function(module, extraPosition) {
462
+ var _this1 = _this;
463
+ var originalHandler = module.handler;
464
+ var wrappedHandler = function() {
465
+ for(var _len = arguments.length, allArgs = new Array(_len), _key = 0; _key < _len; _key++){
466
+ allArgs[_key] = arguments[_key];
467
+ }
468
+ return _async_to_generator(function() {
469
+ var _extra_requestInfo, extra, bearerToken, _ref, authInfo, authHeader, headerValue, match, verifyResponse, verifyData, accountId, error, auth;
470
+ return _ts_generator(this, function(_state) {
471
+ switch(_state.label){
472
+ case 0:
473
+ // Extract extra from the correct position
474
+ extra = allArgs[extraPosition];
475
+ // Option 1: Token already verified by SDK's bearerAuth middleware
476
+ if (extra.authInfo && _type_of(extra.authInfo) === 'object') {
477
+ ;
478
+ // authInfo contains the validated token - extract it
479
+ // The SDK's bearerAuth middleware already validated it, but we need the raw token for /oauth/verify
480
+ // Check if authInfo has the token directly, otherwise extract from headers
481
+ authInfo = extra.authInfo;
482
+ bearerToken = (_ref = typeof authInfo.accessToken === 'string' ? authInfo.accessToken : undefined) !== null && _ref !== void 0 ? _ref : typeof authInfo.token === 'string' ? authInfo.token : undefined;
483
+ }
484
+ // Option 2: Extract from Authorization header
485
+ if (!bearerToken && ((_extra_requestInfo = extra.requestInfo) === null || _extra_requestInfo === void 0 ? void 0 : _extra_requestInfo.headers)) {
486
+ authHeader = extra.requestInfo.headers.authorization || extra.requestInfo.headers.Authorization;
487
+ if (authHeader) {
488
+ // Handle both string and string[] types
489
+ headerValue = Array.isArray(authHeader) ? authHeader[0] : authHeader;
490
+ if (headerValue) {
491
+ match = /^Bearer\s+(.+)$/i.exec(headerValue);
492
+ if (match) {
493
+ bearerToken = match[1];
494
+ }
495
+ }
496
+ }
497
+ }
498
+ if (!bearerToken) {
499
+ throw new _types.McpError(_types.ErrorCode.InvalidRequest, 'Missing Authorization header. DCR mode requires bearer token.');
500
+ }
501
+ return [
502
+ 4,
503
+ fetch(this.config.verifyEndpoint, {
504
+ headers: {
505
+ Authorization: "Bearer ".concat(bearerToken)
506
+ }
507
+ })
508
+ ];
509
+ case 1:
510
+ verifyResponse = _state.sent();
511
+ if (!verifyResponse.ok) {
512
+ throw new _types.McpError(_types.ErrorCode.InvalidRequest, "Token verification failed: ".concat(verifyResponse.status));
513
+ }
514
+ return [
515
+ 4,
516
+ verifyResponse.json()
517
+ ];
518
+ case 2:
519
+ verifyData = _state.sent();
520
+ _state.label = 3;
521
+ case 3:
522
+ _state.trys.push([
523
+ 3,
524
+ 5,
525
+ ,
526
+ 6
527
+ ]);
528
+ return [
529
+ 4,
530
+ this.getUserEmail(verifyData.providerTokens)
531
+ ];
532
+ case 4:
533
+ accountId = _state.sent();
534
+ return [
535
+ 3,
536
+ 6
537
+ ];
538
+ case 5:
539
+ error = _state.sent();
540
+ throw new _types.McpError(_types.ErrorCode.InternalError, "Failed to get user email for DCR authentication: ".concat(_instanceof(error, Error) ? error.message : String(error)));
541
+ case 6:
542
+ // Create auth client from provider tokens
543
+ auth = this.toAuth(verifyData.providerTokens);
544
+ // Inject authContext and logger into extra
545
+ extra.authContext = {
546
+ auth: auth,
547
+ accountId: accountId
548
+ };
549
+ extra.logger = this.config.logger;
550
+ return [
551
+ 4,
552
+ originalHandler.apply(void 0, _to_consumable_array(allArgs))
553
+ ];
554
+ case 7:
555
+ // Call original handler with all args
556
+ return [
557
+ 2,
558
+ _state.sent()
559
+ ];
560
+ }
561
+ });
562
+ }).call(_this1);
563
+ };
564
+ return _object_spread_props(_object_spread({}, module), {
565
+ handler: wrappedHandler
566
+ });
567
+ };
568
+ return {
569
+ // Use structural constraints to avoid contravariance check on handler type.
570
+ // wrapAtPosition is now generic and returns T directly.
571
+ withToolAuth: function(module) {
572
+ return wrapAtPosition(module, 1);
573
+ },
574
+ withResourceAuth: function(module) {
575
+ return wrapAtPosition(module, 2);
576
+ },
577
+ withPromptAuth: function(module) {
578
+ return wrapAtPosition(module, 0);
579
+ }
580
+ };
581
+ };
582
+ return DcrOAuthProvider;
583
+ }();
584
+ /* 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; }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/Projects/ai/mcp-z/oauth/oauth-google/src/providers/dcr.ts"],"sourcesContent":["/**\n * DCR Provider - Stateless Dynamic Client Registration Provider\n *\n * Implements stateless provider pattern where provider tokens are received from\n * token verification context rather than managed by the provider itself.\n *\n * Use case: MCP HTTP servers with DCR authentication where client manages tokens\n * and provider only handles Google API calls with provided credentials.\n */\n\nimport type { ProviderTokens } from '@mcp-z/oauth';\nimport { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';\nimport { OAuth2Client } from 'google-auth-library';\nimport type { AuthContext, EnrichedExtra, Logger } from '../types.ts';\n\n/**\n * DCR Provider configuration\n */\nexport interface DcrOAuthProviderConfig {\n /** Google application client ID */\n clientId: string;\n\n /** Google application client secret (optional for public clients) */\n clientSecret?: string;\n\n /** OAuth scopes */\n scope: string;\n\n /** DCR token verification endpoint URL (e.g., http://localhost:3000/oauth/verify) */\n verifyEndpoint: string;\n\n /** Logger for auth operations */\n logger: Logger;\n}\n\n/**\n * Google TokenResponse\n */\ninterface TokenResponse {\n access_token: string;\n refresh_token?: string;\n expires_in?: number;\n scope?: string;\n token_type?: string;\n}\n\n/**\n * DCR Provider - Stateless OAuth provider for Dynamic Client Registration\n *\n * Unlike LoopbackOAuthProvider which manages token storage, DcrOAuthProvider is stateless:\n * - Receives provider tokens from verification context (HTTP bearer auth)\n * - Creates auth providers on-demand from tokens\n * - Handles token refresh using Google OAuth 2.0\n * - No token storage dependency\n *\n * Pattern:\n * ```typescript\n * const provider = new DcrOAuthProvider(config);\n * const auth = provider.toAuth(providerTokens);\n * const accessToken = await getAccessToken(auth);\n * ```\n */\nexport class DcrOAuthProvider {\n private config: DcrOAuthProviderConfig;\n private emailCache = new Map<string, { email: string; expiresAt: number }>();\n\n constructor(config: DcrOAuthProviderConfig) {\n this.config = config;\n }\n\n /**\n * Create Google OAuth2Client from provider tokens\n *\n * This is the core stateless pattern - provider receives tokens from context\n * (token verification, HTTP request) and creates OAuth2Client on-demand.\n *\n * @param tokens - Provider tokens (Google access/refresh tokens)\n * @returns Google OAuth2Client configured with credentials\n */\n toAuth(tokens: ProviderTokens): OAuth2Client {\n const { clientId, clientSecret } = this.config;\n\n // Create OAuth2Client with credentials\n const client = new OAuth2Client({\n clientId,\n ...(clientSecret && { clientSecret }),\n });\n\n // Set initial credentials (convert undefined to null for Google's Credentials type)\n client.credentials = {\n access_token: tokens.accessToken,\n refresh_token: tokens.refreshToken ?? null,\n expiry_date: tokens.expiresAt ?? null,\n token_type: 'Bearer',\n };\n\n // Override getRequestMetadataAsync to handle token refresh\n // @ts-expect-error - Access protected method for token refresh\n const originalGetMetadata = client.getRequestMetadataAsync.bind(client);\n\n // @ts-expect-error - Override protected method for token refresh\n client.getRequestMetadataAsync = async (url?: string) => {\n // Check if token needs refresh\n if (this.needsRefresh(client.credentials.expiry_date)) {\n try {\n // Use built-in refresh mechanism\n const refreshedTokens = await client.refreshAccessToken();\n client.credentials = refreshedTokens.credentials;\n } catch (error) {\n throw new Error(`Token refresh failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n return originalGetMetadata(url);\n };\n\n return client;\n }\n\n /**\n * Check if token needs refresh (with 1 minute buffer)\n */\n private needsRefresh(expiryDate: number | null | undefined): boolean {\n if (!expiryDate) return false; // No expiry = no refresh needed\n return Date.now() >= expiryDate - 60000; // 1 minute buffer\n }\n\n /**\n * Refresh Google access token using refresh token\n *\n * @param refreshToken - Google refresh token\n * @returns New provider tokens\n */\n async refreshAccessToken(refreshToken: string): Promise<ProviderTokens> {\n const { clientId, clientSecret } = this.config;\n\n const tokenUrl = 'https://oauth2.googleapis.com/token';\n const params: Record<string, string> = {\n refresh_token: refreshToken,\n client_id: clientId,\n grant_type: 'refresh_token',\n };\n\n // Only include client_secret for confidential clients\n if (clientSecret) {\n params.client_secret = clientSecret;\n }\n\n const body = new URLSearchParams(params);\n\n const response = await fetch(tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: body.toString(),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token refresh failed: ${response.status} ${errorText}`);\n }\n\n const tokenResponse = (await response.json()) as TokenResponse;\n\n const result: ProviderTokens = {\n accessToken: tokenResponse.access_token,\n refreshToken: refreshToken, // Keep original refresh token\n };\n\n // Only add optional fields if they have values\n if (tokenResponse.expires_in !== undefined) {\n result.expiresAt = Date.now() + tokenResponse.expires_in * 1000;\n }\n if (tokenResponse.scope !== undefined) {\n result.scope = tokenResponse.scope;\n }\n\n return result;\n }\n\n /**\n * Get user email from Google userinfo API (with caching)\n *\n * @param tokens - Provider tokens to use for API call\n * @returns User's email address\n */\n async getUserEmail(tokens: ProviderTokens): Promise<string> {\n const cacheKey = tokens.accessToken;\n const cached = this.emailCache.get(cacheKey);\n\n // Check cache (with same expiry as access token)\n if (cached && Date.now() < cached.expiresAt) {\n return cached.email;\n }\n\n const auth = this.toAuth(tokens);\n\n // Use OAuth2Client to make authenticated request\n const response = await auth.request({\n url: 'https://www.googleapis.com/oauth2/v2/userinfo',\n method: 'GET',\n });\n\n const userInfo = response.data as { email: string };\n const email = userInfo.email;\n\n // Cache with token expiration (default 1 hour if not specified)\n this.emailCache.set(cacheKey, {\n email,\n expiresAt: tokens.expiresAt ?? Date.now() + 3600000,\n });\n\n return email;\n }\n\n /**\n * Auth middleware for HTTP servers with DCR bearer auth\n * Validates bearer tokens and enriches extra with provider tokens\n *\n * Pattern:\n * ```typescript\n * const provider = new DcrOAuthProvider({ ..., verifyEndpoint: 'http://localhost:3000/oauth/verify' });\n * const authMiddleware = provider.authMiddleware();\n * const tools = toolFactories.map(f => f()).map(authMiddleware.withToolAuth);\n * const resources = resourceFactories.map(f => f()).map(authMiddleware.withResourceAuth);\n * const prompts = promptFactories.map(f => f()).map(authMiddleware.withPromptAuth);\n * ```\n */\n authMiddleware() {\n // Shared wrapper logic - extracts extra parameter from specified position\n // Generic T captures the actual module type; handler is cast from unknown to callable\n const wrapAtPosition = <T extends { name: string; handler: unknown; [key: string]: unknown }>(module: T, extraPosition: number): T => {\n const originalHandler = module.handler as (...args: unknown[]) => Promise<unknown>;\n\n const wrappedHandler = async (...allArgs: unknown[]) => {\n // Extract extra from the correct position\n const extra = allArgs[extraPosition] as EnrichedExtra;\n\n // Extract DCR bearer token from SDK's authInfo (if present) or request headers\n let bearerToken: string | undefined;\n\n // Option 1: Token already verified by SDK's bearerAuth middleware\n if (extra.authInfo && typeof extra.authInfo === 'object') {\n // authInfo contains the validated token - extract it\n // The SDK's bearerAuth middleware already validated it, but we need the raw token for /oauth/verify\n // Check if authInfo has the token directly, otherwise extract from headers\n const authInfo = extra.authInfo as unknown as Record<string, unknown>;\n bearerToken = (typeof authInfo.accessToken === 'string' ? authInfo.accessToken : undefined) ?? (typeof authInfo.token === 'string' ? authInfo.token : undefined);\n }\n\n // Option 2: Extract from Authorization header\n if (!bearerToken && extra.requestInfo?.headers) {\n const authHeader = extra.requestInfo.headers.authorization || extra.requestInfo.headers.Authorization;\n if (authHeader) {\n // Handle both string and string[] types\n const headerValue = Array.isArray(authHeader) ? authHeader[0] : authHeader;\n if (headerValue) {\n const match = /^Bearer\\s+(.+)$/i.exec(headerValue);\n if (match) {\n bearerToken = match[1];\n }\n }\n }\n }\n\n if (!bearerToken) {\n throw new McpError(ErrorCode.InvalidRequest, 'Missing Authorization header. DCR mode requires bearer token.');\n }\n\n // Call /oauth/verify to validate DCR token and get provider tokens\n const verifyResponse = await fetch(this.config.verifyEndpoint, {\n headers: { Authorization: `Bearer ${bearerToken}` },\n });\n\n if (!verifyResponse.ok) {\n throw new McpError(ErrorCode.InvalidRequest, `Token verification failed: ${verifyResponse.status}`);\n }\n\n const verifyData = (await verifyResponse.json()) as {\n providerTokens: ProviderTokens;\n };\n\n // Fetch user email to use as accountId (with caching)\n let accountId: string;\n try {\n accountId = await this.getUserEmail(verifyData.providerTokens);\n } catch (error) {\n throw new McpError(ErrorCode.InternalError, `Failed to get user email for DCR authentication: ${error instanceof Error ? error.message : String(error)}`);\n }\n\n // Create auth client from provider tokens\n const auth = this.toAuth(verifyData.providerTokens);\n\n // Inject authContext and logger into extra\n (extra as { authContext?: AuthContext }).authContext = {\n auth,\n accountId, // User's email address\n };\n (extra as { logger?: unknown }).logger = this.config.logger;\n\n // Call original handler with all args\n return await originalHandler(...allArgs);\n };\n\n return {\n ...module,\n handler: wrappedHandler,\n } as T;\n };\n\n return {\n // Use structural constraints to avoid contravariance check on handler type.\n // wrapAtPosition is now generic and returns T directly.\n withToolAuth: <T extends { name: string; config: unknown; handler: unknown }>(module: T) => wrapAtPosition(module, 1),\n withResourceAuth: <T extends { name: string; template?: unknown; config?: unknown; handler: unknown }>(module: T) => wrapAtPosition(module, 2),\n withPromptAuth: <T extends { name: string; config: unknown; handler: unknown }>(module: T) => wrapAtPosition(module, 0),\n };\n }\n}\n"],"names":["DcrOAuthProvider","config","emailCache","Map","toAuth","tokens","clientId","clientSecret","client","OAuth2Client","credentials","access_token","accessToken","refresh_token","refreshToken","expiry_date","expiresAt","token_type","originalGetMetadata","getRequestMetadataAsync","bind","url","refreshedTokens","error","needsRefresh","refreshAccessToken","Error","message","String","expiryDate","Date","now","tokenUrl","params","body","response","errorText","tokenResponse","result","client_id","grant_type","client_secret","URLSearchParams","fetch","method","headers","toString","ok","text","status","json","expires_in","undefined","scope","getUserEmail","cacheKey","cached","auth","userInfo","email","get","request","data","set","authMiddleware","wrapAtPosition","module","extraPosition","originalHandler","handler","wrappedHandler","allArgs","extra","bearerToken","authInfo","authHeader","headerValue","match","verifyResponse","verifyData","accountId","token","requestInfo","authorization","Authorization","Array","isArray","exec","McpError","ErrorCode","InvalidRequest","verifyEndpoint","providerTokens","InternalError","authContext","logger","withToolAuth","withResourceAuth","withPromptAuth"],"mappings":"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"}