mcp4openapi 0.1.0 → 0.2.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 (151) hide show
  1. package/README.md +134 -95
  2. package/dist/scripts/validate-profile.js +3 -3
  3. package/dist/scripts/validate-profile.js.map +1 -1
  4. package/dist/src/composite-executor.d.ts +3 -1
  5. package/dist/src/composite-executor.d.ts.map +1 -1
  6. package/dist/src/composite-executor.js +16 -5
  7. package/dist/src/composite-executor.js.map +1 -1
  8. package/dist/src/constants.d.ts +49 -0
  9. package/dist/src/constants.d.ts.map +1 -1
  10. package/dist/src/constants.js +49 -0
  11. package/dist/src/constants.js.map +1 -1
  12. package/dist/src/errors.d.ts +6 -0
  13. package/dist/src/errors.d.ts.map +1 -1
  14. package/dist/src/errors.js +13 -0
  15. package/dist/src/errors.js.map +1 -1
  16. package/dist/src/generated-schemas.d.ts +832 -52
  17. package/dist/src/generated-schemas.d.ts.map +1 -1
  18. package/dist/src/generated-schemas.js +31 -8
  19. package/dist/src/generated-schemas.js.map +1 -1
  20. package/dist/src/http-client-factory.d.ts.map +1 -1
  21. package/dist/src/http-client-factory.js +14 -3
  22. package/dist/src/http-client-factory.js.map +1 -1
  23. package/dist/src/http-transport.d.ts +65 -0
  24. package/dist/src/http-transport.d.ts.map +1 -1
  25. package/dist/src/http-transport.js +921 -77
  26. package/dist/src/http-transport.js.map +1 -1
  27. package/dist/src/index.js +108 -8
  28. package/dist/src/index.js.map +1 -1
  29. package/dist/src/interceptors.d.ts +3 -0
  30. package/dist/src/interceptors.d.ts.map +1 -1
  31. package/dist/src/interceptors.js +50 -8
  32. package/dist/src/interceptors.js.map +1 -1
  33. package/dist/src/logger.d.ts +1 -1
  34. package/dist/src/logger.js +3 -3
  35. package/dist/src/logger.js.map +1 -1
  36. package/dist/src/mcp-server.d.ts +33 -0
  37. package/dist/src/mcp-server.d.ts.map +1 -1
  38. package/dist/src/mcp-server.js +263 -54
  39. package/dist/src/mcp-server.js.map +1 -1
  40. package/dist/src/oauth-provider.d.ts +92 -0
  41. package/dist/src/oauth-provider.d.ts.map +1 -0
  42. package/dist/src/oauth-provider.js +588 -0
  43. package/dist/src/oauth-provider.js.map +1 -0
  44. package/dist/src/openapi-parser.d.ts +16 -0
  45. package/dist/src/openapi-parser.d.ts.map +1 -1
  46. package/dist/src/openapi-parser.js +141 -6
  47. package/dist/src/openapi-parser.js.map +1 -1
  48. package/dist/src/profile-loader.d.ts +2 -2
  49. package/dist/src/profile-loader.d.ts.map +1 -1
  50. package/dist/src/profile-loader.js +45 -24
  51. package/dist/src/profile-loader.js.map +1 -1
  52. package/dist/src/testing/fixtures.d.ts +32 -0
  53. package/dist/src/testing/fixtures.d.ts.map +1 -1
  54. package/dist/src/testing/fixtures.js +26 -0
  55. package/dist/src/testing/fixtures.js.map +1 -1
  56. package/dist/src/testing/mock-gitlab-server.d.ts.map +1 -1
  57. package/dist/src/testing/mock-gitlab-server.js +131 -1
  58. package/dist/src/testing/mock-gitlab-server.js.map +1 -1
  59. package/dist/src/types/http-transport.d.ts +16 -0
  60. package/dist/src/types/http-transport.d.ts.map +1 -1
  61. package/dist/src/types/openapi.d.ts +5 -0
  62. package/dist/src/types/openapi.d.ts.map +1 -1
  63. package/dist/src/types/profile.d.ts +112 -3
  64. package/dist/src/types/profile.d.ts.map +1 -1
  65. package/dist/src/validation-utils.d.ts +12 -0
  66. package/dist/src/validation-utils.d.ts.map +1 -1
  67. package/dist/src/validation-utils.js +17 -0
  68. package/dist/src/validation-utils.js.map +1 -1
  69. package/package.json +7 -3
  70. package/profile-schema.json +169 -7
  71. package/dist/composite-executor.d.ts +0 -65
  72. package/dist/composite-executor.d.ts.map +0 -1
  73. package/dist/composite-executor.js +0 -147
  74. package/dist/composite-executor.js.map +0 -1
  75. package/dist/constants.d.ts +0 -36
  76. package/dist/constants.d.ts.map +0 -1
  77. package/dist/constants.js +0 -36
  78. package/dist/constants.js.map +0 -1
  79. package/dist/http-transport.d.ts +0 -195
  80. package/dist/http-transport.d.ts.map +0 -1
  81. package/dist/http-transport.js +0 -760
  82. package/dist/http-transport.js.map +0 -1
  83. package/dist/interceptors.d.ts +0 -74
  84. package/dist/interceptors.d.ts.map +0 -1
  85. package/dist/interceptors.js +0 -220
  86. package/dist/interceptors.js.map +0 -1
  87. package/dist/logger.d.ts +0 -81
  88. package/dist/logger.d.ts.map +0 -1
  89. package/dist/logger.js +0 -264
  90. package/dist/logger.js.map +0 -1
  91. package/dist/mcp-server.d.ts +0 -110
  92. package/dist/mcp-server.d.ts.map +0 -1
  93. package/dist/mcp-server.js +0 -568
  94. package/dist/mcp-server.js.map +0 -1
  95. package/dist/metrics.d.ts +0 -86
  96. package/dist/metrics.d.ts.map +0 -1
  97. package/dist/metrics.js +0 -229
  98. package/dist/metrics.js.map +0 -1
  99. package/dist/openapi-parser.d.ts +0 -35
  100. package/dist/openapi-parser.d.ts.map +0 -1
  101. package/dist/openapi-parser.js +0 -160
  102. package/dist/openapi-parser.js.map +0 -1
  103. package/dist/profile-loader.d.ts +0 -25
  104. package/dist/profile-loader.d.ts.map +0 -1
  105. package/dist/profile-loader.js +0 -134
  106. package/dist/profile-loader.js.map +0 -1
  107. package/dist/schema-validator.d.ts +0 -32
  108. package/dist/schema-validator.d.ts.map +0 -1
  109. package/dist/schema-validator.js +0 -126
  110. package/dist/schema-validator.js.map +0 -1
  111. package/dist/testing/fixtures.d.ts +0 -186
  112. package/dist/testing/fixtures.d.ts.map +0 -1
  113. package/dist/testing/fixtures.js +0 -135
  114. package/dist/testing/fixtures.js.map +0 -1
  115. package/dist/testing/http-integration.test.d.ts +0 -7
  116. package/dist/testing/http-integration.test.d.ts.map +0 -1
  117. package/dist/testing/http-integration.test.js +0 -383
  118. package/dist/testing/http-integration.test.js.map +0 -1
  119. package/dist/testing/http-multiuser.test.d.ts +0 -10
  120. package/dist/testing/http-multiuser.test.d.ts.map +0 -1
  121. package/dist/testing/http-multiuser.test.js +0 -255
  122. package/dist/testing/http-multiuser.test.js.map +0 -1
  123. package/dist/testing/integration.test.d.ts +0 -8
  124. package/dist/testing/integration.test.d.ts.map +0 -1
  125. package/dist/testing/integration.test.js +0 -247
  126. package/dist/testing/integration.test.js.map +0 -1
  127. package/dist/testing/mock-gitlab-server.d.ts +0 -34
  128. package/dist/testing/mock-gitlab-server.d.ts.map +0 -1
  129. package/dist/testing/mock-gitlab-server.js +0 -224
  130. package/dist/testing/mock-gitlab-server.js.map +0 -1
  131. package/dist/testing/test-types.d.ts +0 -59
  132. package/dist/testing/test-types.d.ts.map +0 -1
  133. package/dist/testing/test-types.js +0 -7
  134. package/dist/testing/test-types.js.map +0 -1
  135. package/dist/tool-generator.d.ts +0 -43
  136. package/dist/tool-generator.d.ts.map +0 -1
  137. package/dist/tool-generator.js +0 -123
  138. package/dist/tool-generator.js.map +0 -1
  139. package/dist/tsconfig.tsbuildinfo +0 -1
  140. package/dist/types/http-transport.d.ts +0 -39
  141. package/dist/types/http-transport.d.ts.map +0 -1
  142. package/dist/types/http-transport.js +0 -8
  143. package/dist/types/http-transport.js.map +0 -1
  144. package/dist/types/openapi.d.ts +0 -50
  145. package/dist/types/openapi.d.ts.map +0 -1
  146. package/dist/types/openapi.js +0 -9
  147. package/dist/types/openapi.js.map +0 -1
  148. package/dist/types/profile.d.ts +0 -76
  149. package/dist/types/profile.d.ts.map +0 -1
  150. package/dist/types/profile.js +0 -9
  151. package/dist/types/profile.js.map +0 -1
@@ -0,0 +1,588 @@
1
+ /**
2
+ * OAuth 2.0 Provider Adapter
3
+ *
4
+ * Implements MCP SDK OAuthServerProvider interface to integrate with external
5
+ * OAuth 2.0 authorization servers (e.g., GitLab, GitHub, etc.)
6
+ *
7
+ * Architecture:
8
+ * - This server acts as an OAuth client to the external provider (Proxy/Gateway)
9
+ * - Implements "Callback Mode":
10
+ * 1. Client -> MCP (Authorize) -> MCP redirects to Provider (with MCP callback URL)
11
+ * 2. Provider -> MCP (Callback) -> MCP exchanges code for tokens
12
+ * 3. MCP redirects to Client (with Internal Code)
13
+ * 4. Client -> MCP (Token) -> MCP returns stored tokens
14
+ */
15
+ import { randomUUID, createHash } from 'node:crypto';
16
+ import { OAUTH_PATHS } from './constants.js';
17
+ import { escapeHtmlSafe } from './validation-utils.js';
18
+ /**
19
+ * In-memory store for OAuth client registrations
20
+ */
21
+ export class InMemoryClientsStore {
22
+ clients = new Map();
23
+ async getClient(clientId) {
24
+ return this.clients.get(clientId);
25
+ }
26
+ async registerClient(clientMetadata) {
27
+ this.clients.set(clientMetadata.client_id, clientMetadata);
28
+ return clientMetadata;
29
+ }
30
+ }
31
+ /**
32
+ * OAuth Provider Adapter for external OAuth servers
33
+ */
34
+ export class ExternalOAuthProvider {
35
+ config;
36
+ logger;
37
+ _clientsStore;
38
+ // In-memory storage
39
+ authorizationCodes = new Map();
40
+ accessTokens = new Map();
41
+ stateStore = new Map();
42
+ endpointsInitialized = false;
43
+ initializationPromise = null;
44
+ constructor(config, logger) {
45
+ this.config = config;
46
+ this.logger = logger;
47
+ this._clientsStore = new InMemoryClientsStore();
48
+ // Resolve environment variables in OAuth config
49
+ this.config = this.resolveEnvVars(config);
50
+ // Pre-register mcp-proxy-client for VS Code compatibility
51
+ // VS Code doesn't call /oauth/register endpoint before calling /oauth/authorize
52
+ // This client has empty redirect_uris, allowing any redirect URI (validated at runtime)
53
+ const proxyClient = {
54
+ client_id: 'mcp-proxy-client',
55
+ client_secret: 'mcp-proxy-secret',
56
+ redirect_uris: [], // Empty = allow any redirect URI
57
+ grant_types: ['authorization_code', 'refresh_token'],
58
+ response_types: ['code'],
59
+ scope: this.config.scopes ? this.config.scopes.join(' ') : '',
60
+ };
61
+ this._clientsStore.registerClient(proxyClient);
62
+ this.logger.info('Pre-registered mcp-proxy-client for VS Code compatibility');
63
+ }
64
+ /**
65
+ * Lazy initialization of OAuth endpoints (async)
66
+ * Public method to allow HttpTransport to ensure initialization before client validation
67
+ */
68
+ async ensureEndpointsInitialized() {
69
+ if (this.endpointsInitialized) {
70
+ return;
71
+ }
72
+ // Prevent concurrent initializations
73
+ if (this.initializationPromise) {
74
+ return this.initializationPromise;
75
+ }
76
+ this.initializationPromise = (async () => {
77
+ // Register default client BEFORE deriving endpoints
78
+ // This ensures the client is available immediately, even if endpoint derivation fails
79
+ // The client_id from config should be registered as soon as possible to avoid
80
+ // race conditions where /oauth/authorize is called before initialization completes
81
+ if (this.config.client_id) {
82
+ // Allow localhost and configured redirect_uri for default client
83
+ const allowedUris = [];
84
+ if (this.config.redirect_uri) {
85
+ allowedUris.push(this.config.redirect_uri);
86
+ }
87
+ // Also allow common localhost patterns for development/testing
88
+ allowedUris.push('http://localhost:3003/oauth/callback');
89
+ allowedUris.push('http://127.0.0.1:3003/oauth/callback');
90
+ const defaultClient = {
91
+ client_id: this.config.client_id,
92
+ client_secret: this.config.client_secret,
93
+ redirect_uris: allowedUris,
94
+ grant_types: ['authorization_code', 'refresh_token'],
95
+ response_types: ['code'],
96
+ scope: this.config.scopes ? this.config.scopes.join(' ') : '',
97
+ };
98
+ this._clientsStore.registerClient(defaultClient);
99
+ this.logger.info('Registered default OAuth client', {
100
+ clientId: this.config.client_id,
101
+ redirectUris: allowedUris
102
+ });
103
+ }
104
+ // Derive endpoints from issuer if needed
105
+ this.config = await this.deriveEndpointsFromIssuer(this.config);
106
+ // Validate that we have required endpoints
107
+ if (!this.config.authorization_endpoint || !this.config.token_endpoint) {
108
+ throw new Error('OAuth config must provide either issuer OR both authorization_endpoint and token_endpoint');
109
+ }
110
+ this.logger.info('ExternalOAuthProvider initialized', {
111
+ authEndpoint: this.config.authorization_endpoint,
112
+ tokenEndpoint: this.config.token_endpoint,
113
+ hasClientId: !!this.config.client_id,
114
+ scopes: this.config.scopes || [],
115
+ });
116
+ this.endpointsInitialized = true;
117
+ })();
118
+ return this.initializationPromise;
119
+ }
120
+ get clientsStore() {
121
+ return this._clientsStore;
122
+ }
123
+ get authorizationEndpoint() {
124
+ // May be undefined before ensureEndpointsInitialized() is called
125
+ // when OAuth config provides issuer instead of explicit endpoints
126
+ return this.config.authorization_endpoint;
127
+ }
128
+ get redirectUri() {
129
+ return this.config.redirect_uri;
130
+ }
131
+ get scopes() {
132
+ return this.config.scopes || [];
133
+ }
134
+ /**
135
+ * Fetch OAuth Authorization Server Metadata (RFC 8414)
136
+ */
137
+ async fetchOAuthMetadata(issuerUrl) {
138
+ try {
139
+ // Use URL constructor to properly handle trailing slashes
140
+ const metadataUrl = new URL(OAUTH_PATHS.WELL_KNOWN_AUTHORIZATION_SERVER, issuerUrl).toString();
141
+ const response = await fetch(metadataUrl, {
142
+ headers: { 'Accept': 'application/json' },
143
+ signal: AbortSignal.timeout(5000), // 5 second timeout
144
+ });
145
+ if (!response.ok) {
146
+ return null;
147
+ }
148
+ const metadata = await response.json();
149
+ return {
150
+ authorization_endpoint: metadata.authorization_endpoint,
151
+ token_endpoint: metadata.token_endpoint,
152
+ };
153
+ }
154
+ catch (error) {
155
+ this.logger.debug('OAuth metadata fetch failed', { issuerUrl, error });
156
+ return null;
157
+ }
158
+ }
159
+ /**
160
+ * Resolve environment variable references in OAuth config
161
+ */
162
+ resolveEnvVars(config) {
163
+ const resolve = (value) => {
164
+ if (!value)
165
+ return value;
166
+ const match = value.match(/^\$\{env:([^}]+)\}$/);
167
+ if (match) {
168
+ const envVar = match[1];
169
+ const envValue = process.env[envVar];
170
+ if (!envValue) {
171
+ throw new Error(`Environment variable ${envVar} not found (referenced in OAuth config)`);
172
+ }
173
+ return envValue;
174
+ }
175
+ return value;
176
+ };
177
+ return {
178
+ ...config,
179
+ issuer: resolve(config.issuer),
180
+ authorization_endpoint: resolve(config.authorization_endpoint) || config.authorization_endpoint,
181
+ token_endpoint: resolve(config.token_endpoint) || config.token_endpoint,
182
+ client_id: resolve(config.client_id),
183
+ client_secret: resolve(config.client_secret),
184
+ redirect_uri: resolve(config.redirect_uri),
185
+ registration_endpoint: resolve(config.registration_endpoint),
186
+ introspection_endpoint: resolve(config.introspection_endpoint),
187
+ revocation_endpoint: resolve(config.revocation_endpoint),
188
+ };
189
+ }
190
+ /**
191
+ * Derive OAuth endpoints from issuer if needed
192
+ */
193
+ async deriveEndpointsFromIssuer(config) {
194
+ // If both endpoints are explicitly provided, no need to derive
195
+ if (config.authorization_endpoint && config.token_endpoint) {
196
+ return config;
197
+ }
198
+ // If issuer is not provided, we can't derive
199
+ if (!config.issuer) {
200
+ if (!config.authorization_endpoint || !config.token_endpoint) {
201
+ throw new Error('OAuth config must provide either issuer OR both authorization_endpoint and token_endpoint');
202
+ }
203
+ return config;
204
+ }
205
+ const issuer = config.issuer;
206
+ this.logger.info('Deriving OAuth endpoints from issuer', { issuer });
207
+ // Try to fetch OAuth metadata
208
+ const metadata = await this.fetchOAuthMetadata(issuer);
209
+ if (metadata) {
210
+ this.logger.info('Successfully discovered OAuth endpoints', {
211
+ authorization_endpoint: metadata.authorization_endpoint,
212
+ token_endpoint: metadata.token_endpoint,
213
+ });
214
+ return {
215
+ ...config,
216
+ authorization_endpoint: config.authorization_endpoint || metadata.authorization_endpoint,
217
+ token_endpoint: config.token_endpoint || metadata.token_endpoint,
218
+ };
219
+ }
220
+ // Fallback to standard OAuth paths
221
+ this.logger.info('OAuth metadata fetch failed, using standard OAuth paths', { issuer });
222
+ return {
223
+ ...config,
224
+ authorization_endpoint: config.authorization_endpoint || `${issuer}/oauth/authorize`,
225
+ token_endpoint: config.token_endpoint || `${issuer}/oauth/token`,
226
+ };
227
+ }
228
+ /**
229
+ * Begin authorization flow
230
+ * Stores state and redirects to External Provider with MCP Callback URI
231
+ */
232
+ async authorize(client, params, res) {
233
+ await this.ensureEndpointsInitialized();
234
+ this.logger.info('Starting OAuth authorization', {
235
+ clientId: client.client_id,
236
+ scopes: params.scopes,
237
+ redirectUri: params.redirectUri,
238
+ registeredUris: client.redirect_uris,
239
+ });
240
+ // Validate redirect URI
241
+ if (client.redirect_uris && client.redirect_uris.length > 0 && !client.redirect_uris.includes(params.redirectUri)) {
242
+ this.logger.error('Invalid redirect URI', undefined, {
243
+ providedUri: params.redirectUri,
244
+ registeredUris: client.redirect_uris,
245
+ });
246
+ throw new Error('Unregistered redirect_uri');
247
+ }
248
+ const stateToken = randomUUID();
249
+ this.stateStore.set(stateToken, {
250
+ clientRedirectUri: params.redirectUri,
251
+ codeChallenge: params.codeChallenge,
252
+ originalState: params.state,
253
+ clientId: client.client_id,
254
+ scopes: params.scopes,
255
+ });
256
+ const authUrl = new URL(this.config.authorization_endpoint);
257
+ const clientId = this.config.client_id || client.client_id;
258
+ if (!this.config.redirect_uri) {
259
+ throw new Error('MCP4_OAUTH_REDIRECT_URI must be configured');
260
+ }
261
+ const callbackUri = this.config.redirect_uri;
262
+ authUrl.searchParams.set('client_id', clientId);
263
+ authUrl.searchParams.set('redirect_uri', callbackUri);
264
+ authUrl.searchParams.set('response_type', 'code');
265
+ authUrl.searchParams.set('state', stateToken);
266
+ if (params.scopes && params.scopes.length > 0) {
267
+ authUrl.searchParams.set('scope', params.scopes.join(' '));
268
+ }
269
+ else if (this.config.scopes && this.config.scopes.length > 0) {
270
+ authUrl.searchParams.set('scope', this.config.scopes.join(' '));
271
+ }
272
+ // NOTE: Do NOT forward PKCE parameters to external provider
273
+ // The MCP server acts as an OAuth proxy with client_secret (confidential client)
274
+ // PKCE is used only between Cursor <-> MCP, not between MCP <-> External Provider
275
+ // If we forwarded code_challenge, we would need code_verifier which only Cursor has
276
+ this.logger.info('Redirecting to external OAuth provider', {
277
+ authUrl: authUrl.toString(),
278
+ callbackUri,
279
+ stateToken,
280
+ hasClientSecret: !!this.config.client_secret,
281
+ });
282
+ res.redirect(authUrl.toString());
283
+ }
284
+ /**
285
+ * Handle callback from External Provider
286
+ * Exchanges code for tokens and redirects to Client with Internal Code
287
+ */
288
+ async handleCallback(req, res) {
289
+ await this.ensureEndpointsInitialized();
290
+ const { code, state, error } = req.query;
291
+ if (error) {
292
+ this.logger.error('OAuth callback error', undefined, { error, state });
293
+ // Sanitize error messages to prevent XSS
294
+ const safeError = escapeHtmlSafe(error);
295
+ res.status(400);
296
+ res.json({
297
+ error: safeError,
298
+ error_description: `Authorization failed: ${safeError}`
299
+ });
300
+ return;
301
+ }
302
+ if (!code || typeof code !== 'string') {
303
+ res.status(400).send('Missing authorization code');
304
+ return;
305
+ }
306
+ if (!state || typeof state !== 'string') {
307
+ res.status(400).send('Missing state parameter');
308
+ return;
309
+ }
310
+ const storedState = this.stateStore.get(state);
311
+ if (!storedState) {
312
+ res.status(400).send('Invalid or expired state');
313
+ return;
314
+ }
315
+ // Clean up state
316
+ this.stateStore.delete(state);
317
+ try {
318
+ // Exchange External Code for Tokens
319
+ const tokens = await this.exchangeCodeWithProvider(code, undefined, this.config.redirect_uri);
320
+ // Generate Internal Code
321
+ const internalCode = randomUUID();
322
+ // Store Internal Code -> Tokens mapping
323
+ const client = await this._clientsStore.getClient(storedState.clientId);
324
+ if (!client)
325
+ throw new Error('Client not found');
326
+ this.authorizationCodes.set(internalCode, {
327
+ client,
328
+ params: {
329
+ redirectUri: storedState.clientRedirectUri,
330
+ codeChallenge: storedState.codeChallenge,
331
+ scopes: storedState.scopes || [],
332
+ state: storedState.originalState
333
+ },
334
+ createdAt: Date.now(),
335
+ tokens
336
+ });
337
+ // Redirect to Client
338
+ const clientUrl = new URL(storedState.clientRedirectUri);
339
+ clientUrl.searchParams.set('code', internalCode);
340
+ if (storedState.originalState) {
341
+ clientUrl.searchParams.set('state', storedState.originalState);
342
+ }
343
+ this.logger.info('Redirecting to client with internal code', {
344
+ clientUrl: clientUrl.toString(),
345
+ internalCode
346
+ });
347
+ res.redirect(clientUrl.toString());
348
+ }
349
+ catch (err) {
350
+ this.logger.error('Callback handling failed', err);
351
+ res.status(500).send('Internal Server Error during token exchange');
352
+ }
353
+ }
354
+ /**
355
+ * Get code challenge for authorization code (Internal)
356
+ */
357
+ async challengeForAuthorizationCode(client, authorizationCode) {
358
+ const codeData = this.authorizationCodes.get(authorizationCode);
359
+ if (!codeData) {
360
+ throw new Error('Invalid authorization code');
361
+ }
362
+ if (codeData.client.client_id !== client.client_id) {
363
+ throw new Error('Authorization code was not issued to this client');
364
+ }
365
+ return codeData.params.codeChallenge;
366
+ }
367
+ /**
368
+ * Exchange authorization code for access token (Internal)
369
+ */
370
+ async exchangeAuthorizationCode(client, authorizationCode, codeVerifier, redirectUri, resource) {
371
+ await this.ensureEndpointsInitialized();
372
+ this.logger.info('Exchanging internal authorization code', {
373
+ clientId: client.client_id,
374
+ });
375
+ const codeData = this.authorizationCodes.get(authorizationCode);
376
+ if (!codeData) {
377
+ throw new Error('Invalid authorization code');
378
+ }
379
+ if (codeData.client.client_id !== client.client_id) {
380
+ throw new Error('Authorization code was not issued to this client');
381
+ }
382
+ // Validate expiration (5 minutes)
383
+ const codeAge = Date.now() - codeData.createdAt;
384
+ const EXPIRATION_MS = 5 * 60 * 1000; // 5 minutes
385
+ if (codeAge > EXPIRATION_MS) {
386
+ this.authorizationCodes.delete(authorizationCode);
387
+ throw new Error('Authorization code expired');
388
+ }
389
+ // Validate PKCE if code challenge was provided
390
+ if (codeData.params.codeChallenge) {
391
+ if (!codeVerifier) {
392
+ throw new Error('code_verifier is required for PKCE');
393
+ }
394
+ // Verify code challenge (S256 method)
395
+ const hash = createHash('sha256').update(codeVerifier).digest('base64url');
396
+ if (hash !== codeData.params.codeChallenge) {
397
+ throw new Error('Invalid code_verifier');
398
+ }
399
+ }
400
+ if (!codeData.tokens) {
401
+ throw new Error('No tokens associated with this code');
402
+ }
403
+ // Delete authorization code (single use)
404
+ this.authorizationCodes.delete(authorizationCode);
405
+ // Store access token for validation
406
+ const tokenData = {
407
+ token: codeData.tokens.access_token,
408
+ clientId: client.client_id,
409
+ scopes: codeData.params.scopes || this.config.scopes || [],
410
+ expiresAt: codeData.tokens.expires_in
411
+ ? Date.now() + codeData.tokens.expires_in * 1000
412
+ : undefined,
413
+ resource,
414
+ };
415
+ this.accessTokens.set(codeData.tokens.access_token, tokenData);
416
+ return codeData.tokens;
417
+ }
418
+ /**
419
+ * Exchange authorization code with external OAuth provider
420
+ */
421
+ async exchangeCodeWithProvider(code, codeVerifier, redirectUri) {
422
+ const tokenUrl = this.config.token_endpoint;
423
+ const body = new URLSearchParams({
424
+ grant_type: 'authorization_code',
425
+ code,
426
+ redirect_uri: redirectUri,
427
+ });
428
+ if (codeVerifier) {
429
+ body.set('code_verifier', codeVerifier);
430
+ }
431
+ if (this.config.client_id) {
432
+ body.set('client_id', this.config.client_id);
433
+ }
434
+ if (this.config.client_secret) {
435
+ body.set('client_secret', this.config.client_secret);
436
+ }
437
+ this.logger.debug('Exchanging code with external provider', { tokenUrl });
438
+ const response = await fetch(tokenUrl, {
439
+ method: 'POST',
440
+ headers: {
441
+ 'Content-Type': 'application/x-www-form-urlencoded',
442
+ 'Accept': 'application/json',
443
+ },
444
+ body: body.toString(),
445
+ });
446
+ if (!response.ok) {
447
+ const errorText = await response.text();
448
+ this.logger.error('Token exchange failed', undefined, {
449
+ httpStatus: response.status,
450
+ errorMessage: errorText,
451
+ });
452
+ throw new Error(`Token exchange failed: ${response.status} ${errorText}`);
453
+ }
454
+ const tokenResponse = await response.json();
455
+ return tokenResponse;
456
+ }
457
+ async exchangeRefreshToken(client, refreshToken, scopes, resource) {
458
+ await this.ensureEndpointsInitialized();
459
+ this.logger.info('Exchanging refresh token', { clientId: client.client_id });
460
+ const tokenUrl = this.config.token_endpoint;
461
+ const body = new URLSearchParams({
462
+ grant_type: 'refresh_token',
463
+ refresh_token: refreshToken,
464
+ });
465
+ if (scopes && scopes.length > 0) {
466
+ body.set('scope', scopes.join(' '));
467
+ }
468
+ if (this.config.client_id) {
469
+ body.set('client_id', this.config.client_id);
470
+ }
471
+ if (this.config.client_secret) {
472
+ body.set('client_secret', this.config.client_secret);
473
+ }
474
+ const response = await fetch(tokenUrl, {
475
+ method: 'POST',
476
+ headers: {
477
+ 'Content-Type': 'application/x-www-form-urlencoded',
478
+ 'Accept': 'application/json',
479
+ },
480
+ body: body.toString(),
481
+ });
482
+ if (!response.ok) {
483
+ const errorText = await response.text();
484
+ this.logger.error('Refresh token exchange failed', undefined, {
485
+ httpStatus: response.status,
486
+ errorMessage: errorText,
487
+ });
488
+ throw new Error(`Refresh token exchange failed: ${response.status}`);
489
+ }
490
+ const tokenResponse = await response.json();
491
+ const tokenData = {
492
+ token: tokenResponse.access_token,
493
+ clientId: client.client_id,
494
+ scopes: scopes || this.config.scopes || [],
495
+ expiresAt: tokenResponse.expires_in
496
+ ? Date.now() + tokenResponse.expires_in * 1000
497
+ : undefined,
498
+ resource,
499
+ };
500
+ this.accessTokens.set(tokenResponse.access_token, tokenData);
501
+ return tokenResponse;
502
+ }
503
+ async verifyAccessToken(token) {
504
+ const tokenData = this.accessTokens.get(token);
505
+ if (!tokenData) {
506
+ if (this.config.introspection_endpoint) {
507
+ return await this.introspectToken(token);
508
+ }
509
+ throw new Error('Invalid or expired token');
510
+ }
511
+ if (tokenData.expiresAt && tokenData.expiresAt < Date.now()) {
512
+ this.accessTokens.delete(token);
513
+ throw new Error('Token expired');
514
+ }
515
+ return {
516
+ token,
517
+ clientId: tokenData.clientId,
518
+ scopes: tokenData.scopes,
519
+ expiresAt: tokenData.expiresAt ? Math.floor(tokenData.expiresAt / 1000) : undefined,
520
+ resource: tokenData.resource,
521
+ };
522
+ }
523
+ async introspectToken(token) {
524
+ const introspectionUrl = this.config.introspection_endpoint;
525
+ if (!introspectionUrl) {
526
+ throw new Error('Introspection endpoint not configured');
527
+ }
528
+ const body = new URLSearchParams({ token });
529
+ if (this.config.client_id) {
530
+ body.set('client_id', this.config.client_id);
531
+ }
532
+ if (this.config.client_secret) {
533
+ body.set('client_secret', this.config.client_secret);
534
+ }
535
+ const response = await fetch(introspectionUrl, {
536
+ method: 'POST',
537
+ headers: {
538
+ 'Content-Type': 'application/x-www-form-urlencoded',
539
+ 'Accept': 'application/json',
540
+ },
541
+ body: body.toString(),
542
+ });
543
+ if (!response.ok) {
544
+ throw new Error(`Token introspection failed: ${response.status}`);
545
+ }
546
+ const introspectionResponse = await response.json();
547
+ if (!introspectionResponse.active) {
548
+ throw new Error('Token is not active');
549
+ }
550
+ return {
551
+ token,
552
+ clientId: introspectionResponse.client_id || 'unknown',
553
+ scopes: introspectionResponse.scope ? introspectionResponse.scope.split(' ') : [],
554
+ expiresAt: introspectionResponse.exp,
555
+ resource: introspectionResponse.aud ? new URL(introspectionResponse.aud) : undefined,
556
+ };
557
+ }
558
+ async revokeToken(client, request) {
559
+ this.logger.info('Revoking token', { clientId: client.client_id });
560
+ this.accessTokens.delete(request.token);
561
+ if (this.config.revocation_endpoint) {
562
+ await this.revokeTokenWithProvider(request.token);
563
+ }
564
+ }
565
+ async revokeTokenWithProvider(token) {
566
+ const revocationUrl = this.config.revocation_endpoint;
567
+ if (!revocationUrl)
568
+ return;
569
+ const body = new URLSearchParams({ token });
570
+ if (this.config.client_id) {
571
+ body.set('client_id', this.config.client_id);
572
+ }
573
+ if (this.config.client_secret) {
574
+ body.set('client_secret', this.config.client_secret);
575
+ }
576
+ const response = await fetch(revocationUrl, {
577
+ method: 'POST',
578
+ headers: {
579
+ 'Content-Type': 'application/x-www-form-urlencoded',
580
+ },
581
+ body: body.toString(),
582
+ });
583
+ if (!response.ok) {
584
+ this.logger.warn('Token revocation failed', { status: response.status });
585
+ }
586
+ }
587
+ }
588
+ //# sourceMappingURL=oauth-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-provider.js","sourceRoot":"","sources":["../../src/oauth-provider.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,7 @@ import type { OperationInfo, PathInfo } from './types/openapi.js';
8
8
  export declare class OpenAPIParser {
9
9
  private spec?;
10
10
  private index?;
11
+ private schemaCache;
11
12
  load(specPath: string): Promise<void>;
12
13
  /**
13
14
  * Build search index from OpenAPI spec
@@ -27,9 +28,24 @@ export declare class OpenAPIParser {
27
28
  private resolveParameter;
28
29
  private extractRequestBody;
29
30
  private extractSchema;
31
+ private resolveSchema;
32
+ private mergeSchemaInfo;
33
+ private cloneSchemaInfo;
30
34
  getOperation(operationId: string): OperationInfo | undefined;
31
35
  getPath(path: string): PathInfo | undefined;
32
36
  getBaseUrl(): string;
37
+ /**
38
+ * Get resource metadata from OpenAPI spec
39
+ *
40
+ * Why: Used for OAuth 2.0 Protected Resource Metadata (RFC 8707)
41
+ * to provide human-readable name and documentation URL for the API.
42
+ *
43
+ * Returns undefined for fields not present in spec.
44
+ */
45
+ getResourceMetadata(): {
46
+ name?: string;
47
+ documentation?: string;
48
+ };
33
49
  getAllOperations(): OperationInfo[];
34
50
  /**
35
51
  * Get first security scheme from OpenAPI spec
@@ -1 +1 @@
1
- {"version":3,"file":"openapi-parser.d.ts","sourceRoot":"","sources":["../../src/openapi-parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAgB,aAAa,EAAiB,QAAQ,EAA+B,MAAM,oBAAoB,CAAC;AAE5H,qBAAa,aAAa;IACxB,OAAO,CAAC,IAAI,CAAC,CAAqB;IAClC,OAAO,CAAC,KAAK,CAAC,CAAe;IAEvB,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAa3C;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IAkClB,OAAO,CAAC,oBAAoB;IAiB5B,OAAO,CAAC,iBAAiB;IAqBzB;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,kBAAkB;IAoB1B,OAAO,CAAC,aAAa;IA0BrB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI5D,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAI3C,UAAU,IAAI,MAAM;IAKpB,gBAAgB,IAAI,aAAa,EAAE;IAInC;;;;;;;OAOG;IACH,iBAAiB,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS;CAoD/F"}
1
+ {"version":3,"file":"openapi-parser.d.ts","sourceRoot":"","sources":["../../src/openapi-parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAgB,aAAa,EAAiB,QAAQ,EAA+B,MAAM,oBAAoB,CAAC;AAE5H,qBAAa,aAAa;IACxB,OAAO,CAAC,IAAI,CAAC,CAAqB;IAClC,OAAO,CAAC,KAAK,CAAC,CAAe;IAC7B,OAAO,CAAC,WAAW,CAAiC;IAE9C,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAc3C;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IAmClB,OAAO,CAAC,oBAAoB;IAiB5B,OAAO,CAAC,iBAAiB;IAqBzB;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,kBAAkB;IAoB1B,OAAO,CAAC,aAAa;IAsDrB,OAAO,CAAC,aAAa;IAyCrB,OAAO,CAAC,eAAe;IA4BvB,OAAO,CAAC,eAAe;IAwCvB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI5D,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAI3C,UAAU,IAAI,MAAM;IAKpB;;;;;;;OAOG;IACH,mBAAmB,IAAI;QACrB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB;IAOD,gBAAgB,IAAI,aAAa,EAAE;IAInC;;;;;;;OAOG;IACH,iBAAiB,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS;CAoD/F"}