@adcp/sdk 13.0.0-rc.4 → 13.0.0-rc.6

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 (175) hide show
  1. package/README.md +7 -1
  2. package/bin/adcp.js +7 -1
  3. package/dist/lib/adapters/property-list-adapter.d.mts +5 -1
  4. package/dist/lib/adapters/property-list-adapter.d.ts +5 -1
  5. package/dist/lib/adapters/property-list-adapter.d.ts.map +1 -1
  6. package/dist/lib/adapters/property-list-adapter.js +7 -7
  7. package/dist/lib/adapters/property-list-adapter.js.map +1 -1
  8. package/dist/lib/adapters/property-list-adapter.mjs +7 -7
  9. package/dist/lib/adapters/property-list-adapter.mjs.map +1 -1
  10. package/dist/lib/auth/oauth/CLIFlowHandler.d.mts +10 -3
  11. package/dist/lib/auth/oauth/CLIFlowHandler.d.ts +10 -3
  12. package/dist/lib/auth/oauth/CLIFlowHandler.d.ts.map +1 -1
  13. package/dist/lib/auth/oauth/CLIFlowHandler.js +40 -4
  14. package/dist/lib/auth/oauth/CLIFlowHandler.js.map +1 -1
  15. package/dist/lib/auth/oauth/CLIFlowHandler.mjs +40 -4
  16. package/dist/lib/auth/oauth/CLIFlowHandler.mjs.map +1 -1
  17. package/dist/lib/auth/oauth/index.d.mts +1 -1
  18. package/dist/lib/auth/oauth/index.d.ts +1 -1
  19. package/dist/lib/auth/oauth/index.d.ts.map +1 -1
  20. package/dist/lib/auth/oauth/index.js +2 -0
  21. package/dist/lib/auth/oauth/index.js.map +1 -1
  22. package/dist/lib/auth/oauth/index.mjs +2 -0
  23. package/dist/lib/auth/oauth/index.mjs.map +1 -1
  24. package/dist/lib/auth/oauth/web-flow.d.mts +12 -0
  25. package/dist/lib/auth/oauth/web-flow.d.ts +12 -0
  26. package/dist/lib/auth/oauth/web-flow.d.ts.map +1 -1
  27. package/dist/lib/auth/oauth/web-flow.js +20 -2
  28. package/dist/lib/auth/oauth/web-flow.js.map +1 -1
  29. package/dist/lib/auth/oauth/web-flow.mjs +19 -2
  30. package/dist/lib/auth/oauth/web-flow.mjs.map +1 -1
  31. package/dist/lib/core/AgentClient.d.ts.map +1 -1
  32. package/dist/lib/core/SingleAgentClient.d.mts +27 -1
  33. package/dist/lib/core/SingleAgentClient.d.ts +27 -1
  34. package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
  35. package/dist/lib/core/SingleAgentClient.js +46 -18
  36. package/dist/lib/core/SingleAgentClient.js.map +1 -1
  37. package/dist/lib/core/SingleAgentClient.mjs +46 -18
  38. package/dist/lib/core/SingleAgentClient.mjs.map +1 -1
  39. package/dist/lib/net/address-guards.d.ts.map +1 -1
  40. package/dist/lib/net/address-guards.js +4 -0
  41. package/dist/lib/net/address-guards.js.map +1 -1
  42. package/dist/lib/net/address-guards.mjs +4 -0
  43. package/dist/lib/net/address-guards.mjs.map +1 -1
  44. package/dist/lib/protocols/a2a.js +2 -2
  45. package/dist/lib/protocols/a2a.js.map +1 -1
  46. package/dist/lib/protocols/a2a.mjs +2 -2
  47. package/dist/lib/protocols/a2a.mjs.map +1 -1
  48. package/dist/lib/protocols/index.d.ts.map +1 -1
  49. package/dist/lib/protocols/index.js +28 -7
  50. package/dist/lib/protocols/index.js.map +1 -1
  51. package/dist/lib/protocols/index.mjs +28 -7
  52. package/dist/lib/protocols/index.mjs.map +1 -1
  53. package/dist/lib/protocols/mcp-modern.d.ts.map +1 -1
  54. package/dist/lib/protocols/mcp-modern.js +18 -5
  55. package/dist/lib/protocols/mcp-modern.js.map +1 -1
  56. package/dist/lib/protocols/mcp-modern.mjs +18 -5
  57. package/dist/lib/protocols/mcp-modern.mjs.map +1 -1
  58. package/dist/lib/protocols/mcp-tasks.d.ts.map +1 -1
  59. package/dist/lib/protocols/mcp-tasks.js +2 -12
  60. package/dist/lib/protocols/mcp-tasks.js.map +1 -1
  61. package/dist/lib/protocols/mcp-tasks.mjs +2 -12
  62. package/dist/lib/protocols/mcp-tasks.mjs.map +1 -1
  63. package/dist/lib/protocols/mcp.js +2 -2
  64. package/dist/lib/protocols/mcp.js.map +1 -1
  65. package/dist/lib/protocols/mcp.mjs +2 -2
  66. package/dist/lib/protocols/mcp.mjs.map +1 -1
  67. package/dist/lib/registry/types.generated.d.mts +554 -15
  68. package/dist/lib/registry/types.generated.d.ts +554 -15
  69. package/dist/lib/registry/types.generated.d.ts.map +1 -1
  70. package/dist/lib/registry/types.generated.js.map +1 -1
  71. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  72. package/dist/lib/server/decisioning/account.d.mts +6 -4
  73. package/dist/lib/server/decisioning/account.d.ts +6 -4
  74. package/dist/lib/server/decisioning/account.d.ts.map +1 -1
  75. package/dist/lib/server/decisioning/account.js.map +1 -1
  76. package/dist/lib/server/decisioning/account.mjs.map +1 -1
  77. package/dist/lib/server/decisioning/manifest-helpers.d.mts +6 -5
  78. package/dist/lib/server/decisioning/manifest-helpers.d.ts +6 -5
  79. package/dist/lib/server/decisioning/manifest-helpers.d.ts.map +1 -1
  80. package/dist/lib/server/decisioning/manifest-helpers.js.map +1 -1
  81. package/dist/lib/server/decisioning/manifest-helpers.mjs.map +1 -1
  82. package/dist/lib/server/decisioning/runtime/from-platform.js +4 -2
  83. package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
  84. package/dist/lib/server/decisioning/runtime/from-platform.mjs +4 -2
  85. package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
  86. package/dist/lib/server/decisioning/tenant-store.d.mts +26 -14
  87. package/dist/lib/server/decisioning/tenant-store.d.ts +26 -14
  88. package/dist/lib/server/decisioning/tenant-store.d.ts.map +1 -1
  89. package/dist/lib/server/decisioning/tenant-store.js +6 -1
  90. package/dist/lib/server/decisioning/tenant-store.js.map +1 -1
  91. package/dist/lib/server/decisioning/tenant-store.mjs +6 -1
  92. package/dist/lib/server/decisioning/tenant-store.mjs.map +1 -1
  93. package/dist/lib/server/pin-and-bind-fetch.d.mts +2 -0
  94. package/dist/lib/server/pin-and-bind-fetch.d.ts +2 -0
  95. package/dist/lib/server/pin-and-bind-fetch.d.ts.map +1 -1
  96. package/dist/lib/server/pin-and-bind-fetch.js +2 -0
  97. package/dist/lib/server/pin-and-bind-fetch.js.map +1 -1
  98. package/dist/lib/server/pin-and-bind-fetch.mjs +2 -0
  99. package/dist/lib/server/pin-and-bind-fetch.mjs.map +1 -1
  100. package/dist/lib/server/structured-serialize.d.ts.map +1 -1
  101. package/dist/lib/server/structured-serialize.js +10 -2
  102. package/dist/lib/server/structured-serialize.js.map +1 -1
  103. package/dist/lib/server/structured-serialize.mjs +10 -2
  104. package/dist/lib/server/structured-serialize.mjs.map +1 -1
  105. package/dist/lib/server/webhook-emitter.d.ts.map +1 -1
  106. package/dist/lib/server/webhook-emitter.js +4 -2
  107. package/dist/lib/server/webhook-emitter.js.map +1 -1
  108. package/dist/lib/server/webhook-emitter.mjs +4 -2
  109. package/dist/lib/server/webhook-emitter.mjs.map +1 -1
  110. package/dist/lib/signing/middleware.d.mts +2 -1
  111. package/dist/lib/signing/middleware.d.ts +2 -1
  112. package/dist/lib/signing/middleware.d.ts.map +1 -1
  113. package/dist/lib/signing/middleware.js +26 -4
  114. package/dist/lib/signing/middleware.js.map +1 -1
  115. package/dist/lib/signing/middleware.mjs +26 -4
  116. package/dist/lib/signing/middleware.mjs.map +1 -1
  117. package/dist/lib/signing/webhook-verifier.d.ts.map +1 -1
  118. package/dist/lib/signing/webhook-verifier.js +4 -2
  119. package/dist/lib/signing/webhook-verifier.js.map +1 -1
  120. package/dist/lib/signing/webhook-verifier.mjs +4 -2
  121. package/dist/lib/signing/webhook-verifier.mjs.map +1 -1
  122. package/dist/lib/testing/agent-tester.d.ts.map +1 -1
  123. package/dist/lib/testing/agent-tester.js +46 -1
  124. package/dist/lib/testing/agent-tester.js.map +1 -1
  125. package/dist/lib/testing/agent-tester.mjs +46 -1
  126. package/dist/lib/testing/agent-tester.mjs.map +1 -1
  127. package/dist/lib/types/asset-instances.d.mts +8 -6
  128. package/dist/lib/types/asset-instances.d.ts +8 -6
  129. package/dist/lib/types/asset-instances.d.ts.map +1 -1
  130. package/dist/lib/types/asset-instances.js.map +1 -1
  131. package/dist/lib/types/index.d.ts.map +1 -1
  132. package/dist/lib/types/index.js.map +1 -1
  133. package/dist/lib/types/index.mjs.map +1 -1
  134. package/dist/lib/utils/capabilities.d.mts +2 -0
  135. package/dist/lib/utils/capabilities.d.ts +2 -0
  136. package/dist/lib/utils/capabilities.d.ts.map +1 -1
  137. package/dist/lib/utils/capabilities.js +2 -1
  138. package/dist/lib/utils/capabilities.js.map +1 -1
  139. package/dist/lib/utils/capabilities.mjs +2 -1
  140. package/dist/lib/utils/capabilities.mjs.map +1 -1
  141. package/dist/lib/utils/probe-policy.d.mts +0 -16
  142. package/dist/lib/utils/probe-policy.d.ts +0 -16
  143. package/dist/lib/utils/probe-policy.d.ts.map +1 -1
  144. package/dist/lib/utils/probe-policy.js +15 -1
  145. package/dist/lib/utils/probe-policy.js.map +1 -1
  146. package/dist/lib/utils/probe-policy.mjs +15 -1
  147. package/dist/lib/utils/probe-policy.mjs.map +1 -1
  148. package/dist/lib/utils/redact-args.d.mts +36 -0
  149. package/dist/lib/utils/redact-args.d.ts +37 -0
  150. package/dist/lib/utils/redact-args.d.ts.map +1 -0
  151. package/dist/lib/utils/redact-args.js +46 -0
  152. package/dist/lib/utils/redact-args.js.map +1 -0
  153. package/dist/lib/utils/redact-args.mjs +22 -0
  154. package/dist/lib/utils/redact-args.mjs.map +1 -0
  155. package/dist/lib/v2/projection/creative-delivery.js +1 -5
  156. package/dist/lib/v2/projection/creative-delivery.js.map +1 -1
  157. package/dist/lib/v2/projection/creative-delivery.mjs +1 -5
  158. package/dist/lib/v2/projection/creative-delivery.mjs.map +1 -1
  159. package/dist/lib/validation/index.d.mts +15 -1
  160. package/dist/lib/validation/index.d.ts +15 -1
  161. package/dist/lib/validation/index.d.ts.map +1 -1
  162. package/dist/lib/validation/index.js +4 -8
  163. package/dist/lib/validation/index.js.map +1 -1
  164. package/dist/lib/validation/index.mjs +4 -8
  165. package/dist/lib/validation/index.mjs.map +1 -1
  166. package/dist/lib/version.d.mts +3 -3
  167. package/dist/lib/version.d.ts +3 -3
  168. package/dist/lib/version.js +3 -3
  169. package/dist/lib/version.js.map +1 -1
  170. package/dist/lib/version.mjs +3 -3
  171. package/dist/lib/version.mjs.map +1 -1
  172. package/examples/hello_seller_adapter_multi_tenant.ts +7 -0
  173. package/package.json +3 -2
  174. package/skills/build-holdco-agent/SKILL.md +19 -0
  175. package/skills/cross-cutting.md +3 -1
@@ -1,5 +1,6 @@
1
1
  import { createServer } from "http";
2
2
  import { spawn } from "child_process";
3
+ import { timingSafeEqual } from "crypto";
3
4
  import { URL } from "url";
4
5
  import { platform } from "os";
5
6
  import { OAuthCancelledError, OAuthTimeoutError } from "./types.mjs";
@@ -9,6 +10,7 @@ class CLIFlowHandler {
9
10
  callbackPath;
10
11
  quiet;
11
12
  server = null;
13
+ expectedState = null;
12
14
  pendingCallback = null;
13
15
  constructor(config = {}) {
14
16
  this.port = config.callbackPort ?? 8766;
@@ -22,8 +24,12 @@ class CLIFlowHandler {
22
24
  /**
23
25
  * Open URL in the user's default browser
24
26
  *
25
- * Uses spawn with separate arguments to avoid command injection risks.
26
- * The URL is passed as an argument, not interpolated into a shell command.
27
+ * Spawns the platform opener directly with the URL as a separate argument, so
28
+ * no command interpreter parses it. Windows uses `rundll32 url.dll` rather
29
+ * than `cmd /c start`: spawning `cmd` makes the interpreter itself the child,
30
+ * so `cmd` would parse `&`, `|`, and `^` in the URL even though `shell` is
31
+ * unset — and authorization URLs carry `&` by construction and derive partly
32
+ * from a discovered `authorization_endpoint`.
27
33
  */
28
34
  async openBrowser(url) {
29
35
  return new Promise((resolve) => {
@@ -35,8 +41,8 @@ class CLIFlowHandler {
35
41
  args = [url];
36
42
  break;
37
43
  case "win32":
38
- command = "cmd";
39
- args = ["/c", "start", "", url];
44
+ command = "rundll32";
45
+ args = ["url.dll,FileProtocolHandler", url];
40
46
  break;
41
47
  default:
42
48
  command = "xdg-open";
@@ -58,6 +64,18 @@ class CLIFlowHandler {
58
64
  });
59
65
  }
60
66
  async redirectToAuthorization(authorizationUrl) {
67
+ if (!["http:", "https:"].includes(authorizationUrl.protocol)) {
68
+ throw new Error(
69
+ `Refusing to open authorization URL with scheme "${authorizationUrl.protocol}" (only http/https)`
70
+ );
71
+ }
72
+ const state = authorizationUrl.searchParams.get("state");
73
+ if (!state) {
74
+ throw new Error(
75
+ 'Authorization URL is missing the "state" parameter; refusing to start a loopback OAuth flow that cannot bind its callback'
76
+ );
77
+ }
78
+ this.expectedState = state;
61
79
  const url = authorizationUrl.toString();
62
80
  if (!this.quiet) {
63
81
  console.log("");
@@ -112,12 +130,22 @@ class CLIFlowHandler {
112
130
  res.end("Not found");
113
131
  return;
114
132
  }
133
+ const state = url.searchParams.get("state");
134
+ if (!this.expectedState || !state || !statesMatch(state, this.expectedState)) {
135
+ const message = "OAuth state mismatch: callback does not correspond to the authorization request";
136
+ this.sendErrorResponse(res, message);
137
+ if (this.pendingCallback) {
138
+ this.pendingCallback.reject(new Error(message));
139
+ }
140
+ return;
141
+ }
115
142
  const code = url.searchParams.get("code");
116
143
  const error = url.searchParams.get("error");
117
144
  const errorDescription = url.searchParams.get("error_description");
118
145
  if (error) {
119
146
  const errorMsg = errorDescription || error;
120
147
  this.sendErrorResponse(res, errorMsg);
148
+ this.expectedState = null;
121
149
  if (this.pendingCallback) {
122
150
  if (error === "access_denied") {
123
151
  this.pendingCallback.reject(new OAuthCancelledError());
@@ -129,6 +157,7 @@ class CLIFlowHandler {
129
157
  }
130
158
  if (!code) {
131
159
  this.sendErrorResponse(res, "No authorization code received");
160
+ this.expectedState = null;
132
161
  if (this.pendingCallback) {
133
162
  this.pendingCallback.reject(new Error("No authorization code received"));
134
163
  }
@@ -227,6 +256,7 @@ class CLIFlowHandler {
227
256
  `);
228
257
  }
229
258
  async cleanup() {
259
+ this.expectedState = null;
230
260
  if (this.server) {
231
261
  return new Promise((resolve) => {
232
262
  this.server.close(() => {
@@ -237,6 +267,12 @@ class CLIFlowHandler {
237
267
  }
238
268
  }
239
269
  }
270
+ function statesMatch(received, expected) {
271
+ const a = Buffer.from(received, "utf8");
272
+ const b = Buffer.from(expected, "utf8");
273
+ if (a.length !== b.length) return false;
274
+ return timingSafeEqual(a, b);
275
+ }
240
276
  function escapeHtml(text) {
241
277
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
242
278
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/auth/oauth/CLIFlowHandler.ts"],"sourcesContent":["/**\n * CLI OAuth flow handler\n *\n * Opens the user's browser for authorization and\n * starts a local HTTP server to receive the callback.\n */\n\nimport { createServer, Server, IncomingMessage, ServerResponse } from 'http';\nimport { spawn } from 'child_process';\nimport { URL } from 'url';\nimport { platform } from 'os';\nimport type { OAuthFlowHandler } from './types';\nimport { OAuthCancelledError, OAuthTimeoutError } from './types';\n\n/**\n * Configuration for CLI OAuth flow\n */\nexport interface CLIFlowHandlerConfig {\n /** Port for the callback server (default: 8766) */\n callbackPort?: number;\n /** Timeout in ms for waiting for callback (default: 300000 = 5 min) */\n timeout?: number;\n /** Custom callback path (default: /callback) */\n callbackPath?: string;\n /** Suppress console output */\n quiet?: boolean;\n}\n\n/**\n * CLI OAuth flow handler implementation\n *\n * Handles the OAuth flow for command-line tools by:\n * 1. Opening the authorization URL in the user's default browser\n * 2. Starting a local HTTP server to receive the callback\n * 3. Extracting and returning the authorization code\n *\n * @example\n * ```typescript\n * const flow = new CLIFlowHandler({ callbackPort: 8766 });\n * await flow.redirectToAuthorization(new URL('https://auth.example.com/authorize?...'));\n * const code = await flow.waitForCallback();\n * await flow.cleanup();\n * ```\n */\nexport class CLIFlowHandler implements OAuthFlowHandler {\n private readonly port: number;\n private readonly timeout: number;\n private readonly callbackPath: string;\n private readonly quiet: boolean;\n private server: Server | null = null;\n private pendingCallback: {\n resolve: (code: string) => void;\n reject: (error: Error) => void;\n } | null = null;\n\n constructor(config: CLIFlowHandlerConfig = {}) {\n this.port = config.callbackPort ?? 8766;\n this.timeout = config.timeout ?? 300000; // 5 minutes\n this.callbackPath = config.callbackPath ?? '/callback';\n this.quiet = config.quiet ?? false;\n }\n\n getRedirectUrl(): string {\n return `http://localhost:${this.port}${this.callbackPath}`;\n }\n\n /**\n * Open URL in the user's default browser\n *\n * Uses spawn with separate arguments to avoid command injection risks.\n * The URL is passed as an argument, not interpolated into a shell command.\n */\n private async openBrowser(url: string): Promise<void> {\n return new Promise(resolve => {\n let command: string;\n let args: string[];\n\n switch (platform()) {\n case 'darwin':\n command = 'open';\n args = [url];\n break;\n case 'win32':\n command = 'cmd';\n args = ['/c', 'start', '', url];\n break;\n default:\n // Linux and others - try xdg-open\n command = 'xdg-open';\n args = [url];\n }\n\n const child = spawn(command, args, {\n detached: true,\n stdio: 'ignore',\n });\n\n child.on('error', error => {\n if (!this.quiet) {\n console.error(`Failed to open browser: ${error.message}`);\n console.log(`Please manually open: ${url}`);\n }\n // Don't reject - user can manually open the URL\n resolve();\n });\n\n // Unref so the parent process can exit\n child.unref();\n resolve();\n });\n }\n\n async redirectToAuthorization(authorizationUrl: URL): Promise<void> {\n const url = authorizationUrl.toString();\n\n if (!this.quiet) {\n console.log('');\n console.log('Opening browser for authorization...');\n console.log(`URL: ${url}`);\n console.log('');\n }\n\n await this.openBrowser(url);\n }\n\n async waitForCallback(): Promise<string> {\n return new Promise((resolve, reject) => {\n // Set up timeout\n const timeoutId = setTimeout(() => {\n this.cleanup();\n reject(new OAuthTimeoutError(undefined, this.timeout));\n }, this.timeout);\n\n this.pendingCallback = {\n resolve: (code: string) => {\n clearTimeout(timeoutId);\n resolve(code);\n },\n reject: (error: Error) => {\n clearTimeout(timeoutId);\n reject(error);\n },\n };\n\n // Start the callback server\n this.server = createServer((req: IncomingMessage, res: ServerResponse) => {\n this.handleRequest(req, res);\n });\n\n this.server.on('error', error => {\n if (this.pendingCallback) {\n this.pendingCallback.reject(new Error(`Callback server error: ${error.message}`));\n }\n });\n\n this.server.listen(this.port, '127.0.0.1', () => {\n if (!this.quiet) {\n console.log(`Waiting for authorization callback on port ${this.port}...`);\n console.log('(Press Ctrl+C to cancel)');\n console.log('');\n }\n });\n });\n }\n\n private handleRequest(req: IncomingMessage, res: ServerResponse): void {\n const url = new URL(req.url || '/', `http://localhost:${this.port}`);\n\n // Ignore favicon requests\n if (url.pathname === '/favicon.ico') {\n res.writeHead(404);\n res.end();\n return;\n }\n\n // Only handle the callback path\n if (url.pathname !== this.callbackPath) {\n res.writeHead(404);\n res.end('Not found');\n return;\n }\n\n const code = url.searchParams.get('code');\n const error = url.searchParams.get('error');\n const errorDescription = url.searchParams.get('error_description');\n\n if (error) {\n const errorMsg = errorDescription || error;\n this.sendErrorResponse(res, errorMsg);\n\n if (this.pendingCallback) {\n if (error === 'access_denied') {\n this.pendingCallback.reject(new OAuthCancelledError());\n } else {\n this.pendingCallback.reject(new Error(`OAuth error: ${errorMsg}`));\n }\n }\n return;\n }\n\n if (!code) {\n this.sendErrorResponse(res, 'No authorization code received');\n if (this.pendingCallback) {\n this.pendingCallback.reject(new Error('No authorization code received'));\n }\n return;\n }\n\n // Success!\n this.sendSuccessResponse(res);\n\n if (this.pendingCallback) {\n this.pendingCallback.resolve(code);\n }\n\n // Clean up after a short delay to ensure response is sent\n setTimeout(() => this.cleanup(), 1000);\n }\n\n private sendSuccessResponse(res: ServerResponse): void {\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(`\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <title>Authorization Successful</title>\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100vh;\n margin: 0;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n }\n .card {\n background: white;\n padding: 40px;\n border-radius: 12px;\n box-shadow: 0 10px 40px rgba(0,0,0,0.2);\n text-align: center;\n max-width: 400px;\n }\n h1 { color: #22c55e; margin-top: 0; }\n p { color: #666; line-height: 1.6; }\n .icon { font-size: 48px; margin-bottom: 20px; color: #22c55e; }\n </style>\n</head>\n<body>\n <div class=\"card\">\n <div class=\"icon\">&#10003;</div>\n <h1>Authorization Successful</h1>\n <p>You can close this window and return to your terminal.</p>\n <p><small>This window will close automatically in 3 seconds...</small></p>\n </div>\n <script>setTimeout(() => window.close(), 3000);</script>\n</body>\n</html>\n `);\n }\n\n private sendErrorResponse(res: ServerResponse, error: string): void {\n res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(`\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <title>Authorization Failed</title>\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100vh;\n margin: 0;\n background: linear-gradient(135deg, #f87171 0%, #dc2626 100%);\n }\n .card {\n background: white;\n padding: 40px;\n border-radius: 12px;\n box-shadow: 0 10px 40px rgba(0,0,0,0.2);\n text-align: center;\n max-width: 400px;\n }\n h1 { color: #dc2626; margin-top: 0; }\n p { color: #666; line-height: 1.6; }\n .error { color: #dc2626; background: #fef2f2; padding: 10px; border-radius: 6px; }\n .icon { font-size: 48px; margin-bottom: 20px; color: #dc2626; }\n </style>\n</head>\n<body>\n <div class=\"card\">\n <div class=\"icon\">&#10007;</div>\n <h1>Authorization Failed</h1>\n <p class=\"error\">${escapeHtml(error)}</p>\n <p>Please close this window and try again.</p>\n </div>\n</body>\n</html>\n `);\n }\n\n async cleanup(): Promise<void> {\n if (this.server) {\n return new Promise(resolve => {\n this.server!.close(() => {\n this.server = null;\n resolve();\n });\n });\n }\n }\n}\n\n/**\n * Escape HTML entities to prevent XSS\n */\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;');\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/lib/auth/oauth/CLIFlowHandler.ts"],"sourcesContent":["/**\n * CLI OAuth flow handler\n *\n * Opens the user's browser for authorization and\n * starts a local HTTP server to receive the callback.\n */\n\nimport { createServer, Server, IncomingMessage, ServerResponse } from 'http';\nimport { spawn } from 'child_process';\nimport { timingSafeEqual } from 'crypto';\nimport { URL } from 'url';\nimport { platform } from 'os';\nimport type { OAuthFlowHandler } from './types';\nimport { OAuthCancelledError, OAuthTimeoutError } from './types';\n\n/**\n * Configuration for CLI OAuth flow\n */\nexport interface CLIFlowHandlerConfig {\n /** Port for the callback server (default: 8766) */\n callbackPort?: number;\n /** Timeout in ms for waiting for callback (default: 300000 = 5 min) */\n timeout?: number;\n /** Custom callback path (default: /callback) */\n callbackPath?: string;\n /** Suppress console output */\n quiet?: boolean;\n}\n\n/**\n * CLI OAuth flow handler implementation\n *\n * Handles the OAuth flow for command-line tools by:\n * 1. Opening the authorization URL in the user's default browser\n * 2. Starting a local HTTP server to receive the callback\n * 3. Extracting and returning the authorization code\n *\n * @example\n * ```typescript\n * const flow = new CLIFlowHandler({ callbackPort: 8766 });\n * // The authorization URL MUST carry `state` — the callback is bound to it.\n * // `MCPOAuthProvider` supplies one automatically via its `state()` method.\n * await flow.redirectToAuthorization(new URL('https://auth.example.com/authorize?client_id=abc&state=<random>'));\n * const code = await flow.waitForCallback();\n * await flow.cleanup();\n * ```\n */\nexport class CLIFlowHandler implements OAuthFlowHandler {\n private readonly port: number;\n private readonly timeout: number;\n private readonly callbackPath: string;\n private readonly quiet: boolean;\n private server: Server | null = null;\n private expectedState: string | null = null;\n private pendingCallback: {\n resolve: (code: string) => void;\n reject: (error: Error) => void;\n } | null = null;\n\n constructor(config: CLIFlowHandlerConfig = {}) {\n this.port = config.callbackPort ?? 8766;\n this.timeout = config.timeout ?? 300000; // 5 minutes\n this.callbackPath = config.callbackPath ?? '/callback';\n this.quiet = config.quiet ?? false;\n }\n\n getRedirectUrl(): string {\n return `http://localhost:${this.port}${this.callbackPath}`;\n }\n\n /**\n * Open URL in the user's default browser\n *\n * Spawns the platform opener directly with the URL as a separate argument, so\n * no command interpreter parses it. Windows uses `rundll32 url.dll` rather\n * than `cmd /c start`: spawning `cmd` makes the interpreter itself the child,\n * so `cmd` would parse `&`, `|`, and `^` in the URL even though `shell` is\n * unset — and authorization URLs carry `&` by construction and derive partly\n * from a discovered `authorization_endpoint`.\n */\n private async openBrowser(url: string): Promise<void> {\n return new Promise(resolve => {\n let command: string;\n let args: string[];\n\n switch (platform()) {\n case 'darwin':\n command = 'open';\n args = [url];\n break;\n case 'win32':\n command = 'rundll32';\n args = ['url.dll,FileProtocolHandler', url];\n break;\n default:\n // Linux and others - try xdg-open\n command = 'xdg-open';\n args = [url];\n }\n\n const child = spawn(command, args, {\n detached: true,\n stdio: 'ignore',\n });\n\n child.on('error', error => {\n if (!this.quiet) {\n console.error(`Failed to open browser: ${error.message}`);\n console.log(`Please manually open: ${url}`);\n }\n // Don't reject - user can manually open the URL\n resolve();\n });\n\n // Unref so the parent process can exit\n child.unref();\n resolve();\n });\n }\n\n async redirectToAuthorization(authorizationUrl: URL): Promise<void> {\n if (!['http:', 'https:'].includes(authorizationUrl.protocol)) {\n throw new Error(\n `Refusing to open authorization URL with scheme \"${authorizationUrl.protocol}\" (only http/https)`\n );\n }\n\n // Capture the state we are about to send so the callback can be bound to\n // this flow. The loopback callback server is reachable by any local process,\n // so without this check any of them could inject or cancel an authorization.\n //\n // Scope, stated honestly: this defeats a process that cannot see the\n // authorization URL, which is the ordinary case. It does NOT defeat a local\n // process running as the same user that reads the URL out of this process's\n // argv (`ps`, /proc/<pid>/cmdline) while the browser opens, or off stdout\n // when not `quiet`. PKCE is what protects the code exchange there.\n const state = authorizationUrl.searchParams.get('state');\n if (!state) {\n throw new Error(\n 'Authorization URL is missing the \"state\" parameter; refusing to start a loopback OAuth flow that cannot bind its callback'\n );\n }\n this.expectedState = state;\n\n const url = authorizationUrl.toString();\n\n if (!this.quiet) {\n console.log('');\n console.log('Opening browser for authorization...');\n console.log(`URL: ${url}`);\n console.log('');\n }\n\n await this.openBrowser(url);\n }\n\n async waitForCallback(): Promise<string> {\n return new Promise((resolve, reject) => {\n // Set up timeout\n const timeoutId = setTimeout(() => {\n this.cleanup();\n reject(new OAuthTimeoutError(undefined, this.timeout));\n }, this.timeout);\n\n this.pendingCallback = {\n resolve: (code: string) => {\n clearTimeout(timeoutId);\n resolve(code);\n },\n reject: (error: Error) => {\n clearTimeout(timeoutId);\n reject(error);\n },\n };\n\n // Start the callback server\n this.server = createServer((req: IncomingMessage, res: ServerResponse) => {\n this.handleRequest(req, res);\n });\n\n this.server.on('error', error => {\n if (this.pendingCallback) {\n this.pendingCallback.reject(new Error(`Callback server error: ${error.message}`));\n }\n });\n\n this.server.listen(this.port, '127.0.0.1', () => {\n if (!this.quiet) {\n console.log(`Waiting for authorization callback on port ${this.port}...`);\n console.log('(Press Ctrl+C to cancel)');\n console.log('');\n }\n });\n });\n }\n\n private handleRequest(req: IncomingMessage, res: ServerResponse): void {\n const url = new URL(req.url || '/', `http://localhost:${this.port}`);\n\n // Ignore favicon requests\n if (url.pathname === '/favicon.ico') {\n res.writeHead(404);\n res.end();\n return;\n }\n\n // Only handle the callback path\n if (url.pathname !== this.callbackPath) {\n res.writeHead(404);\n res.end('Not found');\n return;\n }\n\n // Bind the callback to the flow that started it BEFORE interpreting any of\n // its parameters. An unbound callback is not ours to act on — and that\n // includes its error parameters: reading `error=access_denied` first would\n // let any local process cancel the user's login with no knowledge of the\n // state at all. Code injection and cancellation are the same hole, so the\n // check has to precede both branches.\n const state = url.searchParams.get('state');\n if (!this.expectedState || !state || !statesMatch(state, this.expectedState)) {\n const message = 'OAuth state mismatch: callback does not correspond to the authorization request';\n this.sendErrorResponse(res, message);\n if (this.pendingCallback) {\n this.pendingCallback.reject(new Error(message));\n }\n return;\n }\n\n const code = url.searchParams.get('code');\n const error = url.searchParams.get('error');\n const errorDescription = url.searchParams.get('error_description');\n\n if (error) {\n const errorMsg = errorDescription || error;\n this.sendErrorResponse(res, errorMsg);\n\n this.expectedState = null;\n if (this.pendingCallback) {\n if (error === 'access_denied') {\n this.pendingCallback.reject(new OAuthCancelledError());\n } else {\n this.pendingCallback.reject(new Error(`OAuth error: ${errorMsg}`));\n }\n }\n return;\n }\n\n if (!code) {\n this.sendErrorResponse(res, 'No authorization code received');\n this.expectedState = null;\n if (this.pendingCallback) {\n this.pendingCallback.reject(new Error('No authorization code received'));\n }\n return;\n }\n\n // Success!\n this.sendSuccessResponse(res);\n\n if (this.pendingCallback) {\n this.pendingCallback.resolve(code);\n }\n\n // Clean up after a short delay to ensure response is sent\n setTimeout(() => this.cleanup(), 1000);\n }\n\n private sendSuccessResponse(res: ServerResponse): void {\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(`\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <title>Authorization Successful</title>\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100vh;\n margin: 0;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n }\n .card {\n background: white;\n padding: 40px;\n border-radius: 12px;\n box-shadow: 0 10px 40px rgba(0,0,0,0.2);\n text-align: center;\n max-width: 400px;\n }\n h1 { color: #22c55e; margin-top: 0; }\n p { color: #666; line-height: 1.6; }\n .icon { font-size: 48px; margin-bottom: 20px; color: #22c55e; }\n </style>\n</head>\n<body>\n <div class=\"card\">\n <div class=\"icon\">&#10003;</div>\n <h1>Authorization Successful</h1>\n <p>You can close this window and return to your terminal.</p>\n <p><small>This window will close automatically in 3 seconds...</small></p>\n </div>\n <script>setTimeout(() => window.close(), 3000);</script>\n</body>\n</html>\n `);\n }\n\n private sendErrorResponse(res: ServerResponse, error: string): void {\n res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(`\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <title>Authorization Failed</title>\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100vh;\n margin: 0;\n background: linear-gradient(135deg, #f87171 0%, #dc2626 100%);\n }\n .card {\n background: white;\n padding: 40px;\n border-radius: 12px;\n box-shadow: 0 10px 40px rgba(0,0,0,0.2);\n text-align: center;\n max-width: 400px;\n }\n h1 { color: #dc2626; margin-top: 0; }\n p { color: #666; line-height: 1.6; }\n .error { color: #dc2626; background: #fef2f2; padding: 10px; border-radius: 6px; }\n .icon { font-size: 48px; margin-bottom: 20px; color: #dc2626; }\n </style>\n</head>\n<body>\n <div class=\"card\">\n <div class=\"icon\">&#10007;</div>\n <h1>Authorization Failed</h1>\n <p class=\"error\">${escapeHtml(error)}</p>\n <p>Please close this window and try again.</p>\n </div>\n</body>\n</html>\n `);\n }\n\n async cleanup(): Promise<void> {\n this.expectedState = null;\n if (this.server) {\n return new Promise(resolve => {\n this.server!.close(() => {\n this.server = null;\n resolve();\n });\n });\n }\n }\n}\n\n/**\n * Compare two OAuth state values without leaking their contents through timing.\n */\nfunction statesMatch(received: string, expected: string): boolean {\n const a = Buffer.from(received, 'utf8');\n const b = Buffer.from(expected, 'utf8');\n if (a.length !== b.length) return false;\n return timingSafeEqual(a, b);\n}\n\n/**\n * Escape HTML entities to prevent XSS\n */\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;');\n}\n"],"mappings":"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","names":[]}
@@ -34,7 +34,7 @@ export type { OAuthFlowHandler, OAuthProviderConfig, OAuthConfigStorage, OAuthCl
34
34
  export { DEFAULT_CLIENT_METADATA, OAuthError, OAuthCancelledError, OAuthTimeoutError, toMCPTokens, fromMCPTokens, toMCPClientInfo, fromMCPClientInfo, } from './types.mjs';
35
35
  export { CLIFlowHandler, type CLIFlowHandlerConfig } from './CLIFlowHandler.mjs';
36
36
  export { NonInteractiveFlowHandler, type NonInteractiveFlowHandlerConfig } from './NonInteractiveFlowHandler.mjs';
37
- export { startWebOAuthFlow, completeWebOAuthFlow, safeReturnTo, InMemoryPendingFlowStore, InvalidOrExpiredFlowError, StateMismatchError, TokenExchangeError, ProtectedResourceMetadataError, AgentVanishedDuringFlowError, ConfidentialClientNotAllowedError, DEFAULT_WEB_FLOW_TTL_MS, type PendingWebFlow, type PendingWebFlowStore, type PendingFlowStore, type StartWebFlowOptions, type StartWebFlowResult, type CompleteWebFlowOptions, type CompleteWebFlowResult, } from './web-flow.mjs';
37
+ export { startWebOAuthFlow, completeWebOAuthFlow, safeReturnTo, InMemoryPendingFlowStore, InvalidOrExpiredFlowError, StateMismatchError, BrowserBindingRequiredError, TokenExchangeError, ProtectedResourceMetadataError, AgentVanishedDuringFlowError, ConfidentialClientNotAllowedError, DEFAULT_WEB_FLOW_TTL_MS, type PendingWebFlow, type PendingWebFlowStore, type PendingFlowStore, type StartWebFlowOptions, type StartWebFlowResult, type CompleteWebFlowOptions, type CompleteWebFlowResult, } from './web-flow.mjs';
38
38
  export { MCPOAuthProvider } from './MCPOAuthProvider.mjs';
39
39
  import { MCPOAuthProvider } from './MCPOAuthProvider.mjs';
40
40
  import type { OAuthClientMetadata, OAuthConfigStorage, AgentConfig } from './types.mjs';
@@ -34,7 +34,7 @@ export type { OAuthFlowHandler, OAuthProviderConfig, OAuthConfigStorage, OAuthCl
34
34
  export { DEFAULT_CLIENT_METADATA, OAuthError, OAuthCancelledError, OAuthTimeoutError, toMCPTokens, fromMCPTokens, toMCPClientInfo, fromMCPClientInfo, } from './types';
35
35
  export { CLIFlowHandler, type CLIFlowHandlerConfig } from './CLIFlowHandler';
36
36
  export { NonInteractiveFlowHandler, type NonInteractiveFlowHandlerConfig } from './NonInteractiveFlowHandler';
37
- export { startWebOAuthFlow, completeWebOAuthFlow, safeReturnTo, InMemoryPendingFlowStore, InvalidOrExpiredFlowError, StateMismatchError, TokenExchangeError, ProtectedResourceMetadataError, AgentVanishedDuringFlowError, ConfidentialClientNotAllowedError, DEFAULT_WEB_FLOW_TTL_MS, type PendingWebFlow, type PendingWebFlowStore, type PendingFlowStore, type StartWebFlowOptions, type StartWebFlowResult, type CompleteWebFlowOptions, type CompleteWebFlowResult, } from './web-flow';
37
+ export { startWebOAuthFlow, completeWebOAuthFlow, safeReturnTo, InMemoryPendingFlowStore, InvalidOrExpiredFlowError, StateMismatchError, BrowserBindingRequiredError, TokenExchangeError, ProtectedResourceMetadataError, AgentVanishedDuringFlowError, ConfidentialClientNotAllowedError, DEFAULT_WEB_FLOW_TTL_MS, type PendingWebFlow, type PendingWebFlowStore, type PendingFlowStore, type StartWebFlowOptions, type StartWebFlowResult, type CompleteWebFlowOptions, type CompleteWebFlowResult, } from './web-flow';
38
38
  export { MCPOAuthProvider } from './MCPOAuthProvider';
39
39
  import { MCPOAuthProvider } from './MCPOAuthProvider';
40
40
  import type { OAuthClientMetadata, OAuthConfigStorage, AgentConfig } from './types';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/auth/oauth/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/auth/oauth/index.ts"],"names":[],"mappings":"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"}
@@ -20,6 +20,7 @@ var oauth_exports = {};
20
20
  __export(oauth_exports, {
21
21
  AUTH_DIAGNOSIS_SCHEMA_VERSION: () => import_diagnose.AUTH_DIAGNOSIS_SCHEMA_VERSION,
22
22
  AgentVanishedDuringFlowError: () => import_web_flow.AgentVanishedDuringFlowError,
23
+ BrowserBindingRequiredError: () => import_web_flow.BrowserBindingRequiredError,
23
24
  CLIFlowHandler: () => import_CLIFlowHandler.CLIFlowHandler,
24
25
  ClientCredentialsExchangeError: () => import_ClientCredentialsFlow.ClientCredentialsExchangeError,
25
26
  ConfidentialClientNotAllowedError: () => import_web_flow.ConfidentialClientNotAllowedError,
@@ -162,6 +163,7 @@ function getEffectiveAuthToken(agent) {
162
163
  0 && (module.exports = {
163
164
  AUTH_DIAGNOSIS_SCHEMA_VERSION,
164
165
  AgentVanishedDuringFlowError,
166
+ BrowserBindingRequiredError,
165
167
  CLIFlowHandler,
166
168
  ClientCredentialsExchangeError,
167
169
  ConfidentialClientNotAllowedError,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/auth/oauth/index.ts"],"sourcesContent":["/**\n * OAuth module for MCP authentication\n *\n * OAuth tokens are stored directly in AgentConfig, same as static auth tokens.\n *\n * @example\n * ```typescript\n * import { MCPOAuthProvider, CLIFlowHandler } from '@adcp/sdk';\n *\n * // Agent config - tokens will be stored here\n * const agent: AgentConfig = {\n * id: 'my-agent',\n * name: 'My Agent',\n * agent_uri: 'https://agent.example.com/mcp',\n * protocol: 'mcp',\n * // After OAuth flow completes:\n * // oauth_tokens: { access_token: '...', refresh_token: '...' }\n * };\n *\n * // Create provider with CLI flow handler\n * const provider = new MCPOAuthProvider({\n * agent,\n * flowHandler: new CLIFlowHandler(),\n * storage: myConfigStorage // Optional: persists tokens to file/db\n * });\n *\n * // Use with MCP transport\n * const transport = new StreamableHTTPClientTransport(url, {\n * authProvider: provider\n * });\n * ```\n */\n\n// Types\nexport type {\n OAuthFlowHandler,\n OAuthProviderConfig,\n OAuthConfigStorage,\n OAuthClientInformation,\n OAuthClientInformationFull,\n OAuthClientMetadata,\n OAuthTokens,\n AgentConfig,\n AgentOAuthTokens,\n AgentOAuthClient,\n} from './types';\n\nexport {\n DEFAULT_CLIENT_METADATA,\n OAuthError,\n OAuthCancelledError,\n OAuthTimeoutError,\n toMCPTokens,\n fromMCPTokens,\n toMCPClientInfo,\n fromMCPClientInfo,\n} from './types';\n\n// Flow handlers\nexport { CLIFlowHandler, type CLIFlowHandlerConfig } from './CLIFlowHandler';\nexport { NonInteractiveFlowHandler, type NonInteractiveFlowHandlerConfig } from './NonInteractiveFlowHandler';\n\n// Web (server-side) OAuth flow — companion to CLIFlowHandler for environments\n// where /oauth/start and /oauth/callback may be served by different processes.\n// Note: standalone functions, NOT a class implementing OAuthFlowHandler — see\n// docs/guides/WEB-OAUTH.md for the rationale (the contract spans two requests).\nexport {\n startWebOAuthFlow,\n completeWebOAuthFlow,\n safeReturnTo,\n InMemoryPendingFlowStore,\n InvalidOrExpiredFlowError,\n StateMismatchError,\n TokenExchangeError,\n ProtectedResourceMetadataError,\n AgentVanishedDuringFlowError,\n ConfidentialClientNotAllowedError,\n DEFAULT_WEB_FLOW_TTL_MS,\n type PendingWebFlow,\n type PendingWebFlowStore,\n type PendingFlowStore,\n type StartWebFlowOptions,\n type StartWebFlowResult,\n type CompleteWebFlowOptions,\n type CompleteWebFlowResult,\n} from './web-flow';\n\n// Main provider\nexport { MCPOAuthProvider } from './MCPOAuthProvider';\n\n// ========================================\n// Convenience factory functions\n// ========================================\n\nimport { MCPOAuthProvider } from './MCPOAuthProvider';\nimport { CLIFlowHandler, type CLIFlowHandlerConfig } from './CLIFlowHandler';\nimport { NonInteractiveFlowHandler } from './NonInteractiveFlowHandler';\nimport type { OAuthClientMetadata, OAuthConfigStorage, AgentConfig } from './types';\nimport { DEFAULT_CLIENT_METADATA } from './types';\n\n/**\n * Create an OAuth provider for CLI usage\n *\n * @param agent Agent configuration (tokens stored here)\n * @param options Optional configuration\n * @returns Configured OAuth provider\n *\n * @example\n * ```typescript\n * const agent: AgentConfig = {\n * id: 'my-agent',\n * name: 'My Agent',\n * agent_uri: 'https://agent.example.com/mcp',\n * protocol: 'mcp'\n * };\n *\n * const provider = createCLIOAuthProvider(agent);\n *\n * const transport = new StreamableHTTPClientTransport(url, {\n * authProvider: provider\n * });\n *\n * try {\n * await client.connect(transport);\n * } catch (error) {\n * if (error instanceof UnauthorizedError) {\n * const code = await provider.waitForCallback();\n * await transport.finishAuth(code);\n * await client.connect(transport);\n * }\n * }\n *\n * // After successful auth, agent.oauth_tokens is populated\n * console.log(agent.oauth_tokens);\n * ```\n */\nexport function createCLIOAuthProvider(\n agent: AgentConfig,\n options?: {\n /** Callback port (default: 8766) */\n callbackPort?: number;\n /** Auth timeout in ms (default: 300000 = 5 min) */\n timeout?: number;\n /** Custom client metadata overrides */\n clientMetadata?: Partial<OAuthClientMetadata>;\n /** Suppress console output */\n quiet?: boolean;\n /** Storage for persisting agent config */\n storage?: OAuthConfigStorage;\n /**\n * Allow non-HTTPS resource URLs advertised in RFC 9728 protected-resource\n * metadata. Mirrors the CLI's `--allow-http` flag. Defaults to `false`.\n */\n allowHttp?: boolean;\n }\n): MCPOAuthProvider {\n const flowConfig: CLIFlowHandlerConfig = {\n callbackPort: options?.callbackPort,\n timeout: options?.timeout,\n quiet: options?.quiet,\n };\n const flowHandler = new CLIFlowHandler(flowConfig);\n\n // Build complete client metadata\n const clientMetadata: OAuthClientMetadata = {\n ...DEFAULT_CLIENT_METADATA,\n redirect_uris: [flowHandler.getRedirectUrl().toString()],\n ...options?.clientMetadata,\n };\n\n return new MCPOAuthProvider({\n agent,\n flowHandler,\n storage: options?.storage,\n clientMetadata,\n allowHttp: options?.allowHttp,\n });\n}\n\n/**\n * Create an OAuth provider that uses and auto-refreshes saved tokens but\n * refuses to start a new interactive browser flow. Use this for storyboard\n * runs, scheduled jobs, and other non-interactive contexts where you've\n * already saved tokens via `createCLIOAuthProvider`.\n *\n * If refresh fails (e.g., the refresh_token is revoked or expired), the\n * MCP SDK will throw `UnauthorizedError` at call time — the caller should\n * treat that as a signal to run `adcp --save-auth <alias> --oauth` and retry.\n */\nexport function createNonInteractiveOAuthProvider(\n agent: AgentConfig,\n options?: {\n /** Hint shown in error messages if an interactive flow is attempted. */\n agentHint?: string;\n /** Custom client metadata overrides (inherited from saved registration in practice). */\n clientMetadata?: Partial<OAuthClientMetadata>;\n /** Storage for persisting refreshed tokens back to disk. */\n storage?: OAuthConfigStorage;\n /**\n * Allow non-HTTPS resource URLs advertised in RFC 9728 protected-resource\n * metadata. Mirrors the CLI's `--allow-http` flag. Defaults to `false`.\n */\n allowHttp?: boolean;\n }\n): MCPOAuthProvider {\n const flowHandler = new NonInteractiveFlowHandler({ agentHint: options?.agentHint });\n\n const clientMetadata: OAuthClientMetadata = {\n ...DEFAULT_CLIENT_METADATA,\n redirect_uris: [flowHandler.getRedirectUrl().toString()],\n ...options?.clientMetadata,\n };\n\n return new MCPOAuthProvider({\n agent,\n flowHandler,\n storage: options?.storage,\n clientMetadata,\n allowHttp: options?.allowHttp,\n });\n}\n\n/**\n * Check if an error indicates OAuth is required\n */\nexport function isOAuthRequired(error: unknown): boolean {\n if (error instanceof Error) {\n if (error.name === 'UnauthorizedError') return true;\n const msg = error.message.toLowerCase();\n if (msg.includes('unauthorized') || msg.includes('authentication required') || msg.includes('oauth')) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if an agent has valid OAuth tokens\n */\nexport function hasValidOAuthTokens(agent: AgentConfig): boolean {\n const tokens = agent.oauth_tokens;\n if (!tokens?.access_token) return false;\n\n if (tokens.expires_at) {\n const expiresAt = new Date(tokens.expires_at);\n // Expired if within 5 minutes of expiration\n if (expiresAt.getTime() - Date.now() < 5 * 60 * 1000) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Clear OAuth tokens from an agent config\n */\nexport function clearOAuthTokens(agent: AgentConfig): void {\n delete agent.oauth_tokens;\n delete agent.oauth_client;\n delete agent.oauth_code_verifier;\n}\n\n/**\n * Get the effective auth token for an agent\n * Returns OAuth access_token if available, otherwise static auth_token\n */\nexport function getEffectiveAuthToken(agent: AgentConfig): string | undefined {\n // Prefer OAuth if available and valid\n if (hasValidOAuthTokens(agent)) {\n return agent.oauth_tokens!.access_token;\n }\n // Fall back to static token\n return agent.auth_token;\n}\n\n// OAuth discovery\nexport {\n discoverOAuthMetadata,\n supportsOAuth,\n supportsDynamicRegistration,\n type OAuthMetadata,\n type DiscoveryOptions,\n} from './discovery';\n\n// Diagnostics utilities — for `adcp diagnose-auth` and consumer introspection\nexport {\n parseWWWAuthenticate,\n decodeAccessTokenClaims,\n validateTokenAudience,\n type WWWAuthenticateChallenge,\n type DecodedJWTHeader,\n type DecodedJWTClaims,\n type DecodedAccessToken,\n type TokenAudienceResult,\n} from './diagnostics';\n\n// End-to-end OAuth handshake diagnosis (powers `adcp diagnose-auth`)\nexport {\n runAuthDiagnosis,\n AUTH_DIAGNOSIS_SCHEMA_VERSION,\n type DiagnoseOptions,\n type HttpCapture,\n type DiagnosisStep,\n type Hypothesis,\n type HypothesisVerdict,\n type AuthDiagnosisReport,\n} from './diagnose';\n\n// Zero-config authorization discovery + actionable error type.\n// Raised automatically by `ProtocolClient.callTool` when an MCP agent returns\n// a 401 Bearer challenge and the caller has no saved tokens.\nexport {\n NeedsAuthorizationError,\n discoverAuthorizationRequirements,\n probeAuthChallenge,\n type AuthorizationRequirements,\n type DiscoverAuthorizationOptions,\n} from './authorization-required';\n\n// File-backed `OAuthConfigStorage` implementation (agents.json format).\nexport { createFileOAuthStorage, type FileOAuthStorageOptions } from './file-storage';\n\n// OAuth 2.0 client credentials grant (RFC 6749 §4.4) for machine-to-machine\n// token exchange. Used by the CLI for automated compliance runs where there\n// is no user to walk through an authorization-code flow.\nexport {\n exchangeClientCredentials,\n ensureClientCredentialsTokens,\n ClientCredentialsExchangeError,\n type ExchangeClientCredentialsOptions,\n type EnsureClientCredentialsOptions,\n} from './ClientCredentialsFlow';\n\n// `$ENV:VAR` indirection for client credentials so secrets can live in env\n// vars (CI) rather than on disk in the agent config.\nexport {\n resolveSecret,\n isEnvSecretReference,\n toEnvSecretReference,\n extractEnvSecretName,\n MissingEnvSecretError,\n} from './secret-resolver';\n\n// Type re-export — the credentials struct itself lives in the ADCP core types\n// module alongside `AgentOAuthTokens` / `AgentOAuthClient`.\nexport type { AgentOAuthClientCredentials } from '../../types/adcp';\n\n// Per-agent storage binding — the bridge that lets `callTool` pick up the\n// caller's chosen `OAuthConfigStorage` without a signature change.\nexport { bindAgentStorage, getAgentStorage, unbindAgentStorage } from './storage-registry';\n\n// Re-exported MCP SDK OAuth error types so consumers can discriminate 401 causes\n// without string-matching on error messages. These originate from the MCP server\n// auth module but are the canonical OAuth error classes for client-side handling too.\nexport { InvalidTokenError, InsufficientScopeError } from '@modelcontextprotocol/sdk/server/auth/errors.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA+CA,mBASO;AAGP,4BAA0D;AAC1D,uCAAgF;AAMhF,sBAmBO;AAGP,8BAAiC;AAMjC,IAAAA,2BAAiC;AACjC,IAAAC,yBAA0D;AAC1D,IAAAC,oCAA0C;AAE1C,IAAAC,gBAAwC;AAmLxC,uBAMO;AAGP,yBASO;AAGP,sBASO;AAKP,oCAMO;AAGP,0BAAqE;AAKrE,mCAMO;AAIP,6BAMO;AAQP,8BAAsE;AAKtE,oBAA0D;AA3NnD,SAAS,uBACd,OACA,SAiBkB;AAClB,QAAM,aAAmC;AAAA,IACvC,cAAc,SAAS;AAAA,IACvB,SAAS,SAAS;AAAA,IAClB,OAAO,SAAS;AAAA,EAClB;AACA,QAAM,cAAc,IAAI,sCAAe,UAAU;AAGjD,QAAM,iBAAsC;AAAA,IAC1C,GAAG;AAAA,IACH,eAAe,CAAC,YAAY,eAAe,EAAE,SAAS,CAAC;AAAA,IACvD,GAAG,SAAS;AAAA,EACd;AAEA,SAAO,IAAI,0CAAiB;AAAA,IAC1B;AAAA,IACA;AAAA,IACA,SAAS,SAAS;AAAA,IAClB;AAAA,IACA,WAAW,SAAS;AAAA,EACtB,CAAC;AACH;AAYO,SAAS,kCACd,OACA,SAakB;AAClB,QAAM,cAAc,IAAI,4DAA0B,EAAE,WAAW,SAAS,UAAU,CAAC;AAEnF,QAAM,iBAAsC;AAAA,IAC1C,GAAG;AAAA,IACH,eAAe,CAAC,YAAY,eAAe,EAAE,SAAS,CAAC;AAAA,IACvD,GAAG,SAAS;AAAA,EACd;AAEA,SAAO,IAAI,0CAAiB;AAAA,IAC1B;AAAA,IACA;AAAA,IACA,SAAS,SAAS;AAAA,IAClB;AAAA,IACA,WAAW,SAAS;AAAA,EACtB,CAAC;AACH;AAKO,SAAS,gBAAgB,OAAyB;AACvD,MAAI,iBAAiB,OAAO;AAC1B,QAAI,MAAM,SAAS,oBAAqB,QAAO;AAC/C,UAAM,MAAM,MAAM,QAAQ,YAAY;AACtC,QAAI,IAAI,SAAS,cAAc,KAAK,IAAI,SAAS,yBAAyB,KAAK,IAAI,SAAS,OAAO,GAAG;AACpG,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAKO,SAAS,oBAAoB,OAA6B;AAC/D,QAAM,SAAS,MAAM;AACrB,MAAI,CAAC,QAAQ,aAAc,QAAO;AAElC,MAAI,OAAO,YAAY;AACrB,UAAM,YAAY,IAAI,KAAK,OAAO,UAAU;AAE5C,QAAI,UAAU,QAAQ,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,KAAM;AACpD,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,iBAAiB,OAA0B;AACzD,SAAO,MAAM;AACb,SAAO,MAAM;AACb,SAAO,MAAM;AACf;AAMO,SAAS,sBAAsB,OAAwC;AAE5E,MAAI,oBAAoB,KAAK,GAAG;AAC9B,WAAO,MAAM,aAAc;AAAA,EAC7B;AAEA,SAAO,MAAM;AACf;","names":["import_MCPOAuthProvider","import_CLIFlowHandler","import_NonInteractiveFlowHandler","import_types"]}
1
+ {"version":3,"sources":["../../../../src/lib/auth/oauth/index.ts"],"sourcesContent":["/**\n * OAuth module for MCP authentication\n *\n * OAuth tokens are stored directly in AgentConfig, same as static auth tokens.\n *\n * @example\n * ```typescript\n * import { MCPOAuthProvider, CLIFlowHandler } from '@adcp/sdk';\n *\n * // Agent config - tokens will be stored here\n * const agent: AgentConfig = {\n * id: 'my-agent',\n * name: 'My Agent',\n * agent_uri: 'https://agent.example.com/mcp',\n * protocol: 'mcp',\n * // After OAuth flow completes:\n * // oauth_tokens: { access_token: '...', refresh_token: '...' }\n * };\n *\n * // Create provider with CLI flow handler\n * const provider = new MCPOAuthProvider({\n * agent,\n * flowHandler: new CLIFlowHandler(),\n * storage: myConfigStorage // Optional: persists tokens to file/db\n * });\n *\n * // Use with MCP transport\n * const transport = new StreamableHTTPClientTransport(url, {\n * authProvider: provider\n * });\n * ```\n */\n\n// Types\nexport type {\n OAuthFlowHandler,\n OAuthProviderConfig,\n OAuthConfigStorage,\n OAuthClientInformation,\n OAuthClientInformationFull,\n OAuthClientMetadata,\n OAuthTokens,\n AgentConfig,\n AgentOAuthTokens,\n AgentOAuthClient,\n} from './types';\n\nexport {\n DEFAULT_CLIENT_METADATA,\n OAuthError,\n OAuthCancelledError,\n OAuthTimeoutError,\n toMCPTokens,\n fromMCPTokens,\n toMCPClientInfo,\n fromMCPClientInfo,\n} from './types';\n\n// Flow handlers\nexport { CLIFlowHandler, type CLIFlowHandlerConfig } from './CLIFlowHandler';\nexport { NonInteractiveFlowHandler, type NonInteractiveFlowHandlerConfig } from './NonInteractiveFlowHandler';\n\n// Web (server-side) OAuth flow — companion to CLIFlowHandler for environments\n// where /oauth/start and /oauth/callback may be served by different processes.\n// Note: standalone functions, NOT a class implementing OAuthFlowHandler — see\n// docs/guides/WEB-OAUTH.md for the rationale (the contract spans two requests).\nexport {\n startWebOAuthFlow,\n completeWebOAuthFlow,\n safeReturnTo,\n InMemoryPendingFlowStore,\n InvalidOrExpiredFlowError,\n StateMismatchError,\n BrowserBindingRequiredError,\n TokenExchangeError,\n ProtectedResourceMetadataError,\n AgentVanishedDuringFlowError,\n ConfidentialClientNotAllowedError,\n DEFAULT_WEB_FLOW_TTL_MS,\n type PendingWebFlow,\n type PendingWebFlowStore,\n type PendingFlowStore,\n type StartWebFlowOptions,\n type StartWebFlowResult,\n type CompleteWebFlowOptions,\n type CompleteWebFlowResult,\n} from './web-flow';\n\n// Main provider\nexport { MCPOAuthProvider } from './MCPOAuthProvider';\n\n// ========================================\n// Convenience factory functions\n// ========================================\n\nimport { MCPOAuthProvider } from './MCPOAuthProvider';\nimport { CLIFlowHandler, type CLIFlowHandlerConfig } from './CLIFlowHandler';\nimport { NonInteractiveFlowHandler } from './NonInteractiveFlowHandler';\nimport type { OAuthClientMetadata, OAuthConfigStorage, AgentConfig } from './types';\nimport { DEFAULT_CLIENT_METADATA } from './types';\n\n/**\n * Create an OAuth provider for CLI usage\n *\n * @param agent Agent configuration (tokens stored here)\n * @param options Optional configuration\n * @returns Configured OAuth provider\n *\n * @example\n * ```typescript\n * const agent: AgentConfig = {\n * id: 'my-agent',\n * name: 'My Agent',\n * agent_uri: 'https://agent.example.com/mcp',\n * protocol: 'mcp'\n * };\n *\n * const provider = createCLIOAuthProvider(agent);\n *\n * const transport = new StreamableHTTPClientTransport(url, {\n * authProvider: provider\n * });\n *\n * try {\n * await client.connect(transport);\n * } catch (error) {\n * if (error instanceof UnauthorizedError) {\n * const code = await provider.waitForCallback();\n * await transport.finishAuth(code);\n * await client.connect(transport);\n * }\n * }\n *\n * // After successful auth, agent.oauth_tokens is populated\n * console.log(agent.oauth_tokens);\n * ```\n */\nexport function createCLIOAuthProvider(\n agent: AgentConfig,\n options?: {\n /** Callback port (default: 8766) */\n callbackPort?: number;\n /** Auth timeout in ms (default: 300000 = 5 min) */\n timeout?: number;\n /** Custom client metadata overrides */\n clientMetadata?: Partial<OAuthClientMetadata>;\n /** Suppress console output */\n quiet?: boolean;\n /** Storage for persisting agent config */\n storage?: OAuthConfigStorage;\n /**\n * Allow non-HTTPS resource URLs advertised in RFC 9728 protected-resource\n * metadata. Mirrors the CLI's `--allow-http` flag. Defaults to `false`.\n */\n allowHttp?: boolean;\n }\n): MCPOAuthProvider {\n const flowConfig: CLIFlowHandlerConfig = {\n callbackPort: options?.callbackPort,\n timeout: options?.timeout,\n quiet: options?.quiet,\n };\n const flowHandler = new CLIFlowHandler(flowConfig);\n\n // Build complete client metadata\n const clientMetadata: OAuthClientMetadata = {\n ...DEFAULT_CLIENT_METADATA,\n redirect_uris: [flowHandler.getRedirectUrl().toString()],\n ...options?.clientMetadata,\n };\n\n return new MCPOAuthProvider({\n agent,\n flowHandler,\n storage: options?.storage,\n clientMetadata,\n allowHttp: options?.allowHttp,\n });\n}\n\n/**\n * Create an OAuth provider that uses and auto-refreshes saved tokens but\n * refuses to start a new interactive browser flow. Use this for storyboard\n * runs, scheduled jobs, and other non-interactive contexts where you've\n * already saved tokens via `createCLIOAuthProvider`.\n *\n * If refresh fails (e.g., the refresh_token is revoked or expired), the\n * MCP SDK will throw `UnauthorizedError` at call time — the caller should\n * treat that as a signal to run `adcp --save-auth <alias> --oauth` and retry.\n */\nexport function createNonInteractiveOAuthProvider(\n agent: AgentConfig,\n options?: {\n /** Hint shown in error messages if an interactive flow is attempted. */\n agentHint?: string;\n /** Custom client metadata overrides (inherited from saved registration in practice). */\n clientMetadata?: Partial<OAuthClientMetadata>;\n /** Storage for persisting refreshed tokens back to disk. */\n storage?: OAuthConfigStorage;\n /**\n * Allow non-HTTPS resource URLs advertised in RFC 9728 protected-resource\n * metadata. Mirrors the CLI's `--allow-http` flag. Defaults to `false`.\n */\n allowHttp?: boolean;\n }\n): MCPOAuthProvider {\n const flowHandler = new NonInteractiveFlowHandler({ agentHint: options?.agentHint });\n\n const clientMetadata: OAuthClientMetadata = {\n ...DEFAULT_CLIENT_METADATA,\n redirect_uris: [flowHandler.getRedirectUrl().toString()],\n ...options?.clientMetadata,\n };\n\n return new MCPOAuthProvider({\n agent,\n flowHandler,\n storage: options?.storage,\n clientMetadata,\n allowHttp: options?.allowHttp,\n });\n}\n\n/**\n * Check if an error indicates OAuth is required\n */\nexport function isOAuthRequired(error: unknown): boolean {\n if (error instanceof Error) {\n if (error.name === 'UnauthorizedError') return true;\n const msg = error.message.toLowerCase();\n if (msg.includes('unauthorized') || msg.includes('authentication required') || msg.includes('oauth')) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if an agent has valid OAuth tokens\n */\nexport function hasValidOAuthTokens(agent: AgentConfig): boolean {\n const tokens = agent.oauth_tokens;\n if (!tokens?.access_token) return false;\n\n if (tokens.expires_at) {\n const expiresAt = new Date(tokens.expires_at);\n // Expired if within 5 minutes of expiration\n if (expiresAt.getTime() - Date.now() < 5 * 60 * 1000) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Clear OAuth tokens from an agent config\n */\nexport function clearOAuthTokens(agent: AgentConfig): void {\n delete agent.oauth_tokens;\n delete agent.oauth_client;\n delete agent.oauth_code_verifier;\n}\n\n/**\n * Get the effective auth token for an agent\n * Returns OAuth access_token if available, otherwise static auth_token\n */\nexport function getEffectiveAuthToken(agent: AgentConfig): string | undefined {\n // Prefer OAuth if available and valid\n if (hasValidOAuthTokens(agent)) {\n return agent.oauth_tokens!.access_token;\n }\n // Fall back to static token\n return agent.auth_token;\n}\n\n// OAuth discovery\nexport {\n discoverOAuthMetadata,\n supportsOAuth,\n supportsDynamicRegistration,\n type OAuthMetadata,\n type DiscoveryOptions,\n} from './discovery';\n\n// Diagnostics utilities — for `adcp diagnose-auth` and consumer introspection\nexport {\n parseWWWAuthenticate,\n decodeAccessTokenClaims,\n validateTokenAudience,\n type WWWAuthenticateChallenge,\n type DecodedJWTHeader,\n type DecodedJWTClaims,\n type DecodedAccessToken,\n type TokenAudienceResult,\n} from './diagnostics';\n\n// End-to-end OAuth handshake diagnosis (powers `adcp diagnose-auth`)\nexport {\n runAuthDiagnosis,\n AUTH_DIAGNOSIS_SCHEMA_VERSION,\n type DiagnoseOptions,\n type HttpCapture,\n type DiagnosisStep,\n type Hypothesis,\n type HypothesisVerdict,\n type AuthDiagnosisReport,\n} from './diagnose';\n\n// Zero-config authorization discovery + actionable error type.\n// Raised automatically by `ProtocolClient.callTool` when an MCP agent returns\n// a 401 Bearer challenge and the caller has no saved tokens.\nexport {\n NeedsAuthorizationError,\n discoverAuthorizationRequirements,\n probeAuthChallenge,\n type AuthorizationRequirements,\n type DiscoverAuthorizationOptions,\n} from './authorization-required';\n\n// File-backed `OAuthConfigStorage` implementation (agents.json format).\nexport { createFileOAuthStorage, type FileOAuthStorageOptions } from './file-storage';\n\n// OAuth 2.0 client credentials grant (RFC 6749 §4.4) for machine-to-machine\n// token exchange. Used by the CLI for automated compliance runs where there\n// is no user to walk through an authorization-code flow.\nexport {\n exchangeClientCredentials,\n ensureClientCredentialsTokens,\n ClientCredentialsExchangeError,\n type ExchangeClientCredentialsOptions,\n type EnsureClientCredentialsOptions,\n} from './ClientCredentialsFlow';\n\n// `$ENV:VAR` indirection for client credentials so secrets can live in env\n// vars (CI) rather than on disk in the agent config.\nexport {\n resolveSecret,\n isEnvSecretReference,\n toEnvSecretReference,\n extractEnvSecretName,\n MissingEnvSecretError,\n} from './secret-resolver';\n\n// Type re-export — the credentials struct itself lives in the ADCP core types\n// module alongside `AgentOAuthTokens` / `AgentOAuthClient`.\nexport type { AgentOAuthClientCredentials } from '../../types/adcp';\n\n// Per-agent storage binding — the bridge that lets `callTool` pick up the\n// caller's chosen `OAuthConfigStorage` without a signature change.\nexport { bindAgentStorage, getAgentStorage, unbindAgentStorage } from './storage-registry';\n\n// Re-exported MCP SDK OAuth error types so consumers can discriminate 401 causes\n// without string-matching on error messages. These originate from the MCP server\n// auth module but are the canonical OAuth error classes for client-side handling too.\nexport { InvalidTokenError, InsufficientScopeError } from '@modelcontextprotocol/sdk/server/auth/errors.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA+CA,mBASO;AAGP,4BAA0D;AAC1D,uCAAgF;AAMhF,sBAoBO;AAGP,8BAAiC;AAMjC,IAAAA,2BAAiC;AACjC,IAAAC,yBAA0D;AAC1D,IAAAC,oCAA0C;AAE1C,IAAAC,gBAAwC;AAmLxC,uBAMO;AAGP,yBASO;AAGP,sBASO;AAKP,oCAMO;AAGP,0BAAqE;AAKrE,mCAMO;AAIP,6BAMO;AAQP,8BAAsE;AAKtE,oBAA0D;AA3NnD,SAAS,uBACd,OACA,SAiBkB;AAClB,QAAM,aAAmC;AAAA,IACvC,cAAc,SAAS;AAAA,IACvB,SAAS,SAAS;AAAA,IAClB,OAAO,SAAS;AAAA,EAClB;AACA,QAAM,cAAc,IAAI,sCAAe,UAAU;AAGjD,QAAM,iBAAsC;AAAA,IAC1C,GAAG;AAAA,IACH,eAAe,CAAC,YAAY,eAAe,EAAE,SAAS,CAAC;AAAA,IACvD,GAAG,SAAS;AAAA,EACd;AAEA,SAAO,IAAI,0CAAiB;AAAA,IAC1B;AAAA,IACA;AAAA,IACA,SAAS,SAAS;AAAA,IAClB;AAAA,IACA,WAAW,SAAS;AAAA,EACtB,CAAC;AACH;AAYO,SAAS,kCACd,OACA,SAakB;AAClB,QAAM,cAAc,IAAI,4DAA0B,EAAE,WAAW,SAAS,UAAU,CAAC;AAEnF,QAAM,iBAAsC;AAAA,IAC1C,GAAG;AAAA,IACH,eAAe,CAAC,YAAY,eAAe,EAAE,SAAS,CAAC;AAAA,IACvD,GAAG,SAAS;AAAA,EACd;AAEA,SAAO,IAAI,0CAAiB;AAAA,IAC1B;AAAA,IACA;AAAA,IACA,SAAS,SAAS;AAAA,IAClB;AAAA,IACA,WAAW,SAAS;AAAA,EACtB,CAAC;AACH;AAKO,SAAS,gBAAgB,OAAyB;AACvD,MAAI,iBAAiB,OAAO;AAC1B,QAAI,MAAM,SAAS,oBAAqB,QAAO;AAC/C,UAAM,MAAM,MAAM,QAAQ,YAAY;AACtC,QAAI,IAAI,SAAS,cAAc,KAAK,IAAI,SAAS,yBAAyB,KAAK,IAAI,SAAS,OAAO,GAAG;AACpG,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAKO,SAAS,oBAAoB,OAA6B;AAC/D,QAAM,SAAS,MAAM;AACrB,MAAI,CAAC,QAAQ,aAAc,QAAO;AAElC,MAAI,OAAO,YAAY;AACrB,UAAM,YAAY,IAAI,KAAK,OAAO,UAAU;AAE5C,QAAI,UAAU,QAAQ,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,KAAM;AACpD,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,iBAAiB,OAA0B;AACzD,SAAO,MAAM;AACb,SAAO,MAAM;AACb,SAAO,MAAM;AACf;AAMO,SAAS,sBAAsB,OAAwC;AAE5E,MAAI,oBAAoB,KAAK,GAAG;AAC9B,WAAO,MAAM,aAAc;AAAA,EAC7B;AAEA,SAAO,MAAM;AACf;","names":["import_MCPOAuthProvider","import_CLIFlowHandler","import_NonInteractiveFlowHandler","import_types"]}
@@ -17,6 +17,7 @@ import {
17
17
  InMemoryPendingFlowStore,
18
18
  InvalidOrExpiredFlowError,
19
19
  StateMismatchError,
20
+ BrowserBindingRequiredError,
20
21
  TokenExchangeError,
21
22
  ProtectedResourceMetadataError,
22
23
  AgentVanishedDuringFlowError,
@@ -132,6 +133,7 @@ import { InvalidTokenError, InsufficientScopeError } from "@modelcontextprotocol
132
133
  export {
133
134
  AUTH_DIAGNOSIS_SCHEMA_VERSION,
134
135
  AgentVanishedDuringFlowError,
136
+ BrowserBindingRequiredError,
135
137
  CLIFlowHandler,
136
138
  ClientCredentialsExchangeError,
137
139
  ConfidentialClientNotAllowedError,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/auth/oauth/index.ts"],"sourcesContent":["/**\n * OAuth module for MCP authentication\n *\n * OAuth tokens are stored directly in AgentConfig, same as static auth tokens.\n *\n * @example\n * ```typescript\n * import { MCPOAuthProvider, CLIFlowHandler } from '@adcp/sdk';\n *\n * // Agent config - tokens will be stored here\n * const agent: AgentConfig = {\n * id: 'my-agent',\n * name: 'My Agent',\n * agent_uri: 'https://agent.example.com/mcp',\n * protocol: 'mcp',\n * // After OAuth flow completes:\n * // oauth_tokens: { access_token: '...', refresh_token: '...' }\n * };\n *\n * // Create provider with CLI flow handler\n * const provider = new MCPOAuthProvider({\n * agent,\n * flowHandler: new CLIFlowHandler(),\n * storage: myConfigStorage // Optional: persists tokens to file/db\n * });\n *\n * // Use with MCP transport\n * const transport = new StreamableHTTPClientTransport(url, {\n * authProvider: provider\n * });\n * ```\n */\n\n// Types\nexport type {\n OAuthFlowHandler,\n OAuthProviderConfig,\n OAuthConfigStorage,\n OAuthClientInformation,\n OAuthClientInformationFull,\n OAuthClientMetadata,\n OAuthTokens,\n AgentConfig,\n AgentOAuthTokens,\n AgentOAuthClient,\n} from './types';\n\nexport {\n DEFAULT_CLIENT_METADATA,\n OAuthError,\n OAuthCancelledError,\n OAuthTimeoutError,\n toMCPTokens,\n fromMCPTokens,\n toMCPClientInfo,\n fromMCPClientInfo,\n} from './types';\n\n// Flow handlers\nexport { CLIFlowHandler, type CLIFlowHandlerConfig } from './CLIFlowHandler';\nexport { NonInteractiveFlowHandler, type NonInteractiveFlowHandlerConfig } from './NonInteractiveFlowHandler';\n\n// Web (server-side) OAuth flow — companion to CLIFlowHandler for environments\n// where /oauth/start and /oauth/callback may be served by different processes.\n// Note: standalone functions, NOT a class implementing OAuthFlowHandler — see\n// docs/guides/WEB-OAUTH.md for the rationale (the contract spans two requests).\nexport {\n startWebOAuthFlow,\n completeWebOAuthFlow,\n safeReturnTo,\n InMemoryPendingFlowStore,\n InvalidOrExpiredFlowError,\n StateMismatchError,\n TokenExchangeError,\n ProtectedResourceMetadataError,\n AgentVanishedDuringFlowError,\n ConfidentialClientNotAllowedError,\n DEFAULT_WEB_FLOW_TTL_MS,\n type PendingWebFlow,\n type PendingWebFlowStore,\n type PendingFlowStore,\n type StartWebFlowOptions,\n type StartWebFlowResult,\n type CompleteWebFlowOptions,\n type CompleteWebFlowResult,\n} from './web-flow';\n\n// Main provider\nexport { MCPOAuthProvider } from './MCPOAuthProvider';\n\n// ========================================\n// Convenience factory functions\n// ========================================\n\nimport { MCPOAuthProvider } from './MCPOAuthProvider';\nimport { CLIFlowHandler, type CLIFlowHandlerConfig } from './CLIFlowHandler';\nimport { NonInteractiveFlowHandler } from './NonInteractiveFlowHandler';\nimport type { OAuthClientMetadata, OAuthConfigStorage, AgentConfig } from './types';\nimport { DEFAULT_CLIENT_METADATA } from './types';\n\n/**\n * Create an OAuth provider for CLI usage\n *\n * @param agent Agent configuration (tokens stored here)\n * @param options Optional configuration\n * @returns Configured OAuth provider\n *\n * @example\n * ```typescript\n * const agent: AgentConfig = {\n * id: 'my-agent',\n * name: 'My Agent',\n * agent_uri: 'https://agent.example.com/mcp',\n * protocol: 'mcp'\n * };\n *\n * const provider = createCLIOAuthProvider(agent);\n *\n * const transport = new StreamableHTTPClientTransport(url, {\n * authProvider: provider\n * });\n *\n * try {\n * await client.connect(transport);\n * } catch (error) {\n * if (error instanceof UnauthorizedError) {\n * const code = await provider.waitForCallback();\n * await transport.finishAuth(code);\n * await client.connect(transport);\n * }\n * }\n *\n * // After successful auth, agent.oauth_tokens is populated\n * console.log(agent.oauth_tokens);\n * ```\n */\nexport function createCLIOAuthProvider(\n agent: AgentConfig,\n options?: {\n /** Callback port (default: 8766) */\n callbackPort?: number;\n /** Auth timeout in ms (default: 300000 = 5 min) */\n timeout?: number;\n /** Custom client metadata overrides */\n clientMetadata?: Partial<OAuthClientMetadata>;\n /** Suppress console output */\n quiet?: boolean;\n /** Storage for persisting agent config */\n storage?: OAuthConfigStorage;\n /**\n * Allow non-HTTPS resource URLs advertised in RFC 9728 protected-resource\n * metadata. Mirrors the CLI's `--allow-http` flag. Defaults to `false`.\n */\n allowHttp?: boolean;\n }\n): MCPOAuthProvider {\n const flowConfig: CLIFlowHandlerConfig = {\n callbackPort: options?.callbackPort,\n timeout: options?.timeout,\n quiet: options?.quiet,\n };\n const flowHandler = new CLIFlowHandler(flowConfig);\n\n // Build complete client metadata\n const clientMetadata: OAuthClientMetadata = {\n ...DEFAULT_CLIENT_METADATA,\n redirect_uris: [flowHandler.getRedirectUrl().toString()],\n ...options?.clientMetadata,\n };\n\n return new MCPOAuthProvider({\n agent,\n flowHandler,\n storage: options?.storage,\n clientMetadata,\n allowHttp: options?.allowHttp,\n });\n}\n\n/**\n * Create an OAuth provider that uses and auto-refreshes saved tokens but\n * refuses to start a new interactive browser flow. Use this for storyboard\n * runs, scheduled jobs, and other non-interactive contexts where you've\n * already saved tokens via `createCLIOAuthProvider`.\n *\n * If refresh fails (e.g., the refresh_token is revoked or expired), the\n * MCP SDK will throw `UnauthorizedError` at call time — the caller should\n * treat that as a signal to run `adcp --save-auth <alias> --oauth` and retry.\n */\nexport function createNonInteractiveOAuthProvider(\n agent: AgentConfig,\n options?: {\n /** Hint shown in error messages if an interactive flow is attempted. */\n agentHint?: string;\n /** Custom client metadata overrides (inherited from saved registration in practice). */\n clientMetadata?: Partial<OAuthClientMetadata>;\n /** Storage for persisting refreshed tokens back to disk. */\n storage?: OAuthConfigStorage;\n /**\n * Allow non-HTTPS resource URLs advertised in RFC 9728 protected-resource\n * metadata. Mirrors the CLI's `--allow-http` flag. Defaults to `false`.\n */\n allowHttp?: boolean;\n }\n): MCPOAuthProvider {\n const flowHandler = new NonInteractiveFlowHandler({ agentHint: options?.agentHint });\n\n const clientMetadata: OAuthClientMetadata = {\n ...DEFAULT_CLIENT_METADATA,\n redirect_uris: [flowHandler.getRedirectUrl().toString()],\n ...options?.clientMetadata,\n };\n\n return new MCPOAuthProvider({\n agent,\n flowHandler,\n storage: options?.storage,\n clientMetadata,\n allowHttp: options?.allowHttp,\n });\n}\n\n/**\n * Check if an error indicates OAuth is required\n */\nexport function isOAuthRequired(error: unknown): boolean {\n if (error instanceof Error) {\n if (error.name === 'UnauthorizedError') return true;\n const msg = error.message.toLowerCase();\n if (msg.includes('unauthorized') || msg.includes('authentication required') || msg.includes('oauth')) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if an agent has valid OAuth tokens\n */\nexport function hasValidOAuthTokens(agent: AgentConfig): boolean {\n const tokens = agent.oauth_tokens;\n if (!tokens?.access_token) return false;\n\n if (tokens.expires_at) {\n const expiresAt = new Date(tokens.expires_at);\n // Expired if within 5 minutes of expiration\n if (expiresAt.getTime() - Date.now() < 5 * 60 * 1000) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Clear OAuth tokens from an agent config\n */\nexport function clearOAuthTokens(agent: AgentConfig): void {\n delete agent.oauth_tokens;\n delete agent.oauth_client;\n delete agent.oauth_code_verifier;\n}\n\n/**\n * Get the effective auth token for an agent\n * Returns OAuth access_token if available, otherwise static auth_token\n */\nexport function getEffectiveAuthToken(agent: AgentConfig): string | undefined {\n // Prefer OAuth if available and valid\n if (hasValidOAuthTokens(agent)) {\n return agent.oauth_tokens!.access_token;\n }\n // Fall back to static token\n return agent.auth_token;\n}\n\n// OAuth discovery\nexport {\n discoverOAuthMetadata,\n supportsOAuth,\n supportsDynamicRegistration,\n type OAuthMetadata,\n type DiscoveryOptions,\n} from './discovery';\n\n// Diagnostics utilities — for `adcp diagnose-auth` and consumer introspection\nexport {\n parseWWWAuthenticate,\n decodeAccessTokenClaims,\n validateTokenAudience,\n type WWWAuthenticateChallenge,\n type DecodedJWTHeader,\n type DecodedJWTClaims,\n type DecodedAccessToken,\n type TokenAudienceResult,\n} from './diagnostics';\n\n// End-to-end OAuth handshake diagnosis (powers `adcp diagnose-auth`)\nexport {\n runAuthDiagnosis,\n AUTH_DIAGNOSIS_SCHEMA_VERSION,\n type DiagnoseOptions,\n type HttpCapture,\n type DiagnosisStep,\n type Hypothesis,\n type HypothesisVerdict,\n type AuthDiagnosisReport,\n} from './diagnose';\n\n// Zero-config authorization discovery + actionable error type.\n// Raised automatically by `ProtocolClient.callTool` when an MCP agent returns\n// a 401 Bearer challenge and the caller has no saved tokens.\nexport {\n NeedsAuthorizationError,\n discoverAuthorizationRequirements,\n probeAuthChallenge,\n type AuthorizationRequirements,\n type DiscoverAuthorizationOptions,\n} from './authorization-required';\n\n// File-backed `OAuthConfigStorage` implementation (agents.json format).\nexport { createFileOAuthStorage, type FileOAuthStorageOptions } from './file-storage';\n\n// OAuth 2.0 client credentials grant (RFC 6749 §4.4) for machine-to-machine\n// token exchange. Used by the CLI for automated compliance runs where there\n// is no user to walk through an authorization-code flow.\nexport {\n exchangeClientCredentials,\n ensureClientCredentialsTokens,\n ClientCredentialsExchangeError,\n type ExchangeClientCredentialsOptions,\n type EnsureClientCredentialsOptions,\n} from './ClientCredentialsFlow';\n\n// `$ENV:VAR` indirection for client credentials so secrets can live in env\n// vars (CI) rather than on disk in the agent config.\nexport {\n resolveSecret,\n isEnvSecretReference,\n toEnvSecretReference,\n extractEnvSecretName,\n MissingEnvSecretError,\n} from './secret-resolver';\n\n// Type re-export — the credentials struct itself lives in the ADCP core types\n// module alongside `AgentOAuthTokens` / `AgentOAuthClient`.\nexport type { AgentOAuthClientCredentials } from '../../types/adcp';\n\n// Per-agent storage binding — the bridge that lets `callTool` pick up the\n// caller's chosen `OAuthConfigStorage` without a signature change.\nexport { bindAgentStorage, getAgentStorage, unbindAgentStorage } from './storage-registry';\n\n// Re-exported MCP SDK OAuth error types so consumers can discriminate 401 causes\n// without string-matching on error messages. These originate from the MCP server\n// auth module but are the canonical OAuth error classes for client-side handling too.\nexport { InvalidTokenError, InsufficientScopeError } from '@modelcontextprotocol/sdk/server/auth/errors.js';\n"],"mappings":"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","names":["MCPOAuthProvider","CLIFlowHandler","NonInteractiveFlowHandler","DEFAULT_CLIENT_METADATA"]}
1
+ {"version":3,"sources":["../../../../src/lib/auth/oauth/index.ts"],"sourcesContent":["/**\n * OAuth module for MCP authentication\n *\n * OAuth tokens are stored directly in AgentConfig, same as static auth tokens.\n *\n * @example\n * ```typescript\n * import { MCPOAuthProvider, CLIFlowHandler } from '@adcp/sdk';\n *\n * // Agent config - tokens will be stored here\n * const agent: AgentConfig = {\n * id: 'my-agent',\n * name: 'My Agent',\n * agent_uri: 'https://agent.example.com/mcp',\n * protocol: 'mcp',\n * // After OAuth flow completes:\n * // oauth_tokens: { access_token: '...', refresh_token: '...' }\n * };\n *\n * // Create provider with CLI flow handler\n * const provider = new MCPOAuthProvider({\n * agent,\n * flowHandler: new CLIFlowHandler(),\n * storage: myConfigStorage // Optional: persists tokens to file/db\n * });\n *\n * // Use with MCP transport\n * const transport = new StreamableHTTPClientTransport(url, {\n * authProvider: provider\n * });\n * ```\n */\n\n// Types\nexport type {\n OAuthFlowHandler,\n OAuthProviderConfig,\n OAuthConfigStorage,\n OAuthClientInformation,\n OAuthClientInformationFull,\n OAuthClientMetadata,\n OAuthTokens,\n AgentConfig,\n AgentOAuthTokens,\n AgentOAuthClient,\n} from './types';\n\nexport {\n DEFAULT_CLIENT_METADATA,\n OAuthError,\n OAuthCancelledError,\n OAuthTimeoutError,\n toMCPTokens,\n fromMCPTokens,\n toMCPClientInfo,\n fromMCPClientInfo,\n} from './types';\n\n// Flow handlers\nexport { CLIFlowHandler, type CLIFlowHandlerConfig } from './CLIFlowHandler';\nexport { NonInteractiveFlowHandler, type NonInteractiveFlowHandlerConfig } from './NonInteractiveFlowHandler';\n\n// Web (server-side) OAuth flow — companion to CLIFlowHandler for environments\n// where /oauth/start and /oauth/callback may be served by different processes.\n// Note: standalone functions, NOT a class implementing OAuthFlowHandler — see\n// docs/guides/WEB-OAUTH.md for the rationale (the contract spans two requests).\nexport {\n startWebOAuthFlow,\n completeWebOAuthFlow,\n safeReturnTo,\n InMemoryPendingFlowStore,\n InvalidOrExpiredFlowError,\n StateMismatchError,\n BrowserBindingRequiredError,\n TokenExchangeError,\n ProtectedResourceMetadataError,\n AgentVanishedDuringFlowError,\n ConfidentialClientNotAllowedError,\n DEFAULT_WEB_FLOW_TTL_MS,\n type PendingWebFlow,\n type PendingWebFlowStore,\n type PendingFlowStore,\n type StartWebFlowOptions,\n type StartWebFlowResult,\n type CompleteWebFlowOptions,\n type CompleteWebFlowResult,\n} from './web-flow';\n\n// Main provider\nexport { MCPOAuthProvider } from './MCPOAuthProvider';\n\n// ========================================\n// Convenience factory functions\n// ========================================\n\nimport { MCPOAuthProvider } from './MCPOAuthProvider';\nimport { CLIFlowHandler, type CLIFlowHandlerConfig } from './CLIFlowHandler';\nimport { NonInteractiveFlowHandler } from './NonInteractiveFlowHandler';\nimport type { OAuthClientMetadata, OAuthConfigStorage, AgentConfig } from './types';\nimport { DEFAULT_CLIENT_METADATA } from './types';\n\n/**\n * Create an OAuth provider for CLI usage\n *\n * @param agent Agent configuration (tokens stored here)\n * @param options Optional configuration\n * @returns Configured OAuth provider\n *\n * @example\n * ```typescript\n * const agent: AgentConfig = {\n * id: 'my-agent',\n * name: 'My Agent',\n * agent_uri: 'https://agent.example.com/mcp',\n * protocol: 'mcp'\n * };\n *\n * const provider = createCLIOAuthProvider(agent);\n *\n * const transport = new StreamableHTTPClientTransport(url, {\n * authProvider: provider\n * });\n *\n * try {\n * await client.connect(transport);\n * } catch (error) {\n * if (error instanceof UnauthorizedError) {\n * const code = await provider.waitForCallback();\n * await transport.finishAuth(code);\n * await client.connect(transport);\n * }\n * }\n *\n * // After successful auth, agent.oauth_tokens is populated\n * console.log(agent.oauth_tokens);\n * ```\n */\nexport function createCLIOAuthProvider(\n agent: AgentConfig,\n options?: {\n /** Callback port (default: 8766) */\n callbackPort?: number;\n /** Auth timeout in ms (default: 300000 = 5 min) */\n timeout?: number;\n /** Custom client metadata overrides */\n clientMetadata?: Partial<OAuthClientMetadata>;\n /** Suppress console output */\n quiet?: boolean;\n /** Storage for persisting agent config */\n storage?: OAuthConfigStorage;\n /**\n * Allow non-HTTPS resource URLs advertised in RFC 9728 protected-resource\n * metadata. Mirrors the CLI's `--allow-http` flag. Defaults to `false`.\n */\n allowHttp?: boolean;\n }\n): MCPOAuthProvider {\n const flowConfig: CLIFlowHandlerConfig = {\n callbackPort: options?.callbackPort,\n timeout: options?.timeout,\n quiet: options?.quiet,\n };\n const flowHandler = new CLIFlowHandler(flowConfig);\n\n // Build complete client metadata\n const clientMetadata: OAuthClientMetadata = {\n ...DEFAULT_CLIENT_METADATA,\n redirect_uris: [flowHandler.getRedirectUrl().toString()],\n ...options?.clientMetadata,\n };\n\n return new MCPOAuthProvider({\n agent,\n flowHandler,\n storage: options?.storage,\n clientMetadata,\n allowHttp: options?.allowHttp,\n });\n}\n\n/**\n * Create an OAuth provider that uses and auto-refreshes saved tokens but\n * refuses to start a new interactive browser flow. Use this for storyboard\n * runs, scheduled jobs, and other non-interactive contexts where you've\n * already saved tokens via `createCLIOAuthProvider`.\n *\n * If refresh fails (e.g., the refresh_token is revoked or expired), the\n * MCP SDK will throw `UnauthorizedError` at call time — the caller should\n * treat that as a signal to run `adcp --save-auth <alias> --oauth` and retry.\n */\nexport function createNonInteractiveOAuthProvider(\n agent: AgentConfig,\n options?: {\n /** Hint shown in error messages if an interactive flow is attempted. */\n agentHint?: string;\n /** Custom client metadata overrides (inherited from saved registration in practice). */\n clientMetadata?: Partial<OAuthClientMetadata>;\n /** Storage for persisting refreshed tokens back to disk. */\n storage?: OAuthConfigStorage;\n /**\n * Allow non-HTTPS resource URLs advertised in RFC 9728 protected-resource\n * metadata. Mirrors the CLI's `--allow-http` flag. Defaults to `false`.\n */\n allowHttp?: boolean;\n }\n): MCPOAuthProvider {\n const flowHandler = new NonInteractiveFlowHandler({ agentHint: options?.agentHint });\n\n const clientMetadata: OAuthClientMetadata = {\n ...DEFAULT_CLIENT_METADATA,\n redirect_uris: [flowHandler.getRedirectUrl().toString()],\n ...options?.clientMetadata,\n };\n\n return new MCPOAuthProvider({\n agent,\n flowHandler,\n storage: options?.storage,\n clientMetadata,\n allowHttp: options?.allowHttp,\n });\n}\n\n/**\n * Check if an error indicates OAuth is required\n */\nexport function isOAuthRequired(error: unknown): boolean {\n if (error instanceof Error) {\n if (error.name === 'UnauthorizedError') return true;\n const msg = error.message.toLowerCase();\n if (msg.includes('unauthorized') || msg.includes('authentication required') || msg.includes('oauth')) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if an agent has valid OAuth tokens\n */\nexport function hasValidOAuthTokens(agent: AgentConfig): boolean {\n const tokens = agent.oauth_tokens;\n if (!tokens?.access_token) return false;\n\n if (tokens.expires_at) {\n const expiresAt = new Date(tokens.expires_at);\n // Expired if within 5 minutes of expiration\n if (expiresAt.getTime() - Date.now() < 5 * 60 * 1000) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Clear OAuth tokens from an agent config\n */\nexport function clearOAuthTokens(agent: AgentConfig): void {\n delete agent.oauth_tokens;\n delete agent.oauth_client;\n delete agent.oauth_code_verifier;\n}\n\n/**\n * Get the effective auth token for an agent\n * Returns OAuth access_token if available, otherwise static auth_token\n */\nexport function getEffectiveAuthToken(agent: AgentConfig): string | undefined {\n // Prefer OAuth if available and valid\n if (hasValidOAuthTokens(agent)) {\n return agent.oauth_tokens!.access_token;\n }\n // Fall back to static token\n return agent.auth_token;\n}\n\n// OAuth discovery\nexport {\n discoverOAuthMetadata,\n supportsOAuth,\n supportsDynamicRegistration,\n type OAuthMetadata,\n type DiscoveryOptions,\n} from './discovery';\n\n// Diagnostics utilities — for `adcp diagnose-auth` and consumer introspection\nexport {\n parseWWWAuthenticate,\n decodeAccessTokenClaims,\n validateTokenAudience,\n type WWWAuthenticateChallenge,\n type DecodedJWTHeader,\n type DecodedJWTClaims,\n type DecodedAccessToken,\n type TokenAudienceResult,\n} from './diagnostics';\n\n// End-to-end OAuth handshake diagnosis (powers `adcp diagnose-auth`)\nexport {\n runAuthDiagnosis,\n AUTH_DIAGNOSIS_SCHEMA_VERSION,\n type DiagnoseOptions,\n type HttpCapture,\n type DiagnosisStep,\n type Hypothesis,\n type HypothesisVerdict,\n type AuthDiagnosisReport,\n} from './diagnose';\n\n// Zero-config authorization discovery + actionable error type.\n// Raised automatically by `ProtocolClient.callTool` when an MCP agent returns\n// a 401 Bearer challenge and the caller has no saved tokens.\nexport {\n NeedsAuthorizationError,\n discoverAuthorizationRequirements,\n probeAuthChallenge,\n type AuthorizationRequirements,\n type DiscoverAuthorizationOptions,\n} from './authorization-required';\n\n// File-backed `OAuthConfigStorage` implementation (agents.json format).\nexport { createFileOAuthStorage, type FileOAuthStorageOptions } from './file-storage';\n\n// OAuth 2.0 client credentials grant (RFC 6749 §4.4) for machine-to-machine\n// token exchange. Used by the CLI for automated compliance runs where there\n// is no user to walk through an authorization-code flow.\nexport {\n exchangeClientCredentials,\n ensureClientCredentialsTokens,\n ClientCredentialsExchangeError,\n type ExchangeClientCredentialsOptions,\n type EnsureClientCredentialsOptions,\n} from './ClientCredentialsFlow';\n\n// `$ENV:VAR` indirection for client credentials so secrets can live in env\n// vars (CI) rather than on disk in the agent config.\nexport {\n resolveSecret,\n isEnvSecretReference,\n toEnvSecretReference,\n extractEnvSecretName,\n MissingEnvSecretError,\n} from './secret-resolver';\n\n// Type re-export — the credentials struct itself lives in the ADCP core types\n// module alongside `AgentOAuthTokens` / `AgentOAuthClient`.\nexport type { AgentOAuthClientCredentials } from '../../types/adcp';\n\n// Per-agent storage binding — the bridge that lets `callTool` pick up the\n// caller's chosen `OAuthConfigStorage` without a signature change.\nexport { bindAgentStorage, getAgentStorage, unbindAgentStorage } from './storage-registry';\n\n// Re-exported MCP SDK OAuth error types so consumers can discriminate 401 causes\n// without string-matching on error messages. These originate from the MCP server\n// auth module but are the canonical OAuth error classes for client-side handling too.\nexport { InvalidTokenError, InsufficientScopeError } from '@modelcontextprotocol/sdk/server/auth/errors.js';\n"],"mappings":"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","names":["MCPOAuthProvider","CLIFlowHandler","NonInteractiveFlowHandler","DEFAULT_CLIENT_METADATA"]}
@@ -148,6 +148,9 @@ export declare class AgentVanishedDuringFlowError extends OAuthError {
148
148
  export declare class ConfidentialClientNotAllowedError extends OAuthError {
149
149
  constructor(agentId: string | undefined);
150
150
  }
151
+ export declare class BrowserBindingRequiredError extends OAuthError {
152
+ constructor();
153
+ }
151
154
  export interface StartWebFlowOptions {
152
155
  /** Agent the flow is for. Must include `agent_uri`. */
153
156
  agent: AgentConfig;
@@ -208,6 +211,15 @@ export interface CompleteWebFlowOptions {
208
211
  * but not browser-bound — see WEB-OAUTH.md.
209
212
  */
210
213
  expectedState?: string;
214
+ /**
215
+ * When `true`, throws {@link BrowserBindingRequiredError} if `expectedState`
216
+ * is omitted instead of emitting a `console.warn`. Use this in frameworks
217
+ * where session cookies are always available so that a missing bind is caught
218
+ * at development time rather than silently permitted in production.
219
+ *
220
+ * Default: `false`.
221
+ */
222
+ requireBrowserBinding?: boolean;
211
223
  }
212
224
  export interface CompleteWebFlowResult {
213
225
  agentId: string;
@@ -148,6 +148,9 @@ export declare class AgentVanishedDuringFlowError extends OAuthError {
148
148
  export declare class ConfidentialClientNotAllowedError extends OAuthError {
149
149
  constructor(agentId: string | undefined);
150
150
  }
151
+ export declare class BrowserBindingRequiredError extends OAuthError {
152
+ constructor();
153
+ }
151
154
  export interface StartWebFlowOptions {
152
155
  /** Agent the flow is for. Must include `agent_uri`. */
153
156
  agent: AgentConfig;
@@ -208,6 +211,15 @@ export interface CompleteWebFlowOptions {
208
211
  * but not browser-bound — see WEB-OAUTH.md.
209
212
  */
210
213
  expectedState?: string;
214
+ /**
215
+ * When `true`, throws {@link BrowserBindingRequiredError} if `expectedState`
216
+ * is omitted instead of emitting a `console.warn`. Use this in frameworks
217
+ * where session cookies are always available so that a missing bind is caught
218
+ * at development time rather than silently permitted in production.
219
+ *
220
+ * Default: `false`.
221
+ */
222
+ requireBrowserBinding?: boolean;
211
223
  }
212
224
  export interface CompleteWebFlowResult {
213
225
  agentId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"web-flow.d.ts","sourceRoot":"","sources":["../../../../src/lib/auth/oauth/web-flow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"web-flow.d.ts","sourceRoot":"","sources":["../../../../src/lib/auth/oauth/web-flow.ts"],"names":[],"mappings":"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"}
@@ -19,6 +19,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  var web_flow_exports = {};
20
20
  __export(web_flow_exports, {
21
21
  AgentVanishedDuringFlowError: () => AgentVanishedDuringFlowError,
22
+ BrowserBindingRequiredError: () => BrowserBindingRequiredError,
22
23
  ConfidentialClientNotAllowedError: () => ConfidentialClientNotAllowedError,
23
24
  DEFAULT_WEB_FLOW_TTL_MS: () => DEFAULT_WEB_FLOW_TTL_MS,
24
25
  InMemoryPendingFlowStore: () => InMemoryPendingFlowStore,
@@ -86,6 +87,15 @@ class ConfidentialClientNotAllowedError extends import_types.OAuthError {
86
87
  this.name = "ConfidentialClientNotAllowedError";
87
88
  }
88
89
  }
90
+ class BrowserBindingRequiredError extends import_types.OAuthError {
91
+ constructor() {
92
+ super(
93
+ "completeWebOAuthFlow called with requireBrowserBinding:true but expectedState was not supplied \u2014 pass the state value from the session cookie set at /oauth/start",
94
+ "browser_binding_required"
95
+ );
96
+ this.name = "BrowserBindingRequiredError";
97
+ }
98
+ }
89
99
  async function startWebOAuthFlow(opts) {
90
100
  const {
91
101
  agent,
@@ -161,8 +171,15 @@ async function startWebOAuthFlow(opts) {
161
171
  };
162
172
  }
163
173
  async function completeWebOAuthFlow(opts) {
164
- const { state, code, pendingFlowStore, agentStorage, fetch: fetchFn, expectedState } = opts;
165
- if (expectedState !== void 0 && expectedState !== state) {
174
+ const { state, code, pendingFlowStore, agentStorage, fetch: fetchFn, expectedState, requireBrowserBinding } = opts;
175
+ if (expectedState === void 0) {
176
+ if (requireBrowserBinding) {
177
+ throw new BrowserBindingRequiredError();
178
+ }
179
+ console.warn(
180
+ "[adcp/sdk] completeWebOAuthFlow: expectedState not supplied \u2014 the callback is replay-protected but not browser-bound. Pass expectedState from a session cookie set at /oauth/start, or set requireBrowserBinding:true to enforce it."
181
+ );
182
+ } else if (expectedState !== state) {
166
183
  throw new StateMismatchError();
167
184
  }
168
185
  const flow = await pendingFlowStore.consume(state);
@@ -327,6 +344,7 @@ function redactTokens(input) {
327
344
  // Annotate the CommonJS export names for ESM import in node:
328
345
  0 && (module.exports = {
329
346
  AgentVanishedDuringFlowError,
347
+ BrowserBindingRequiredError,
330
348
  ConfidentialClientNotAllowedError,
331
349
  DEFAULT_WEB_FLOW_TTL_MS,
332
350
  InMemoryPendingFlowStore,