@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.
- package/README.md +7 -1
- package/bin/adcp.js +7 -1
- package/dist/lib/adapters/property-list-adapter.d.mts +5 -1
- package/dist/lib/adapters/property-list-adapter.d.ts +5 -1
- package/dist/lib/adapters/property-list-adapter.d.ts.map +1 -1
- package/dist/lib/adapters/property-list-adapter.js +7 -7
- package/dist/lib/adapters/property-list-adapter.js.map +1 -1
- package/dist/lib/adapters/property-list-adapter.mjs +7 -7
- package/dist/lib/adapters/property-list-adapter.mjs.map +1 -1
- package/dist/lib/auth/oauth/CLIFlowHandler.d.mts +10 -3
- package/dist/lib/auth/oauth/CLIFlowHandler.d.ts +10 -3
- package/dist/lib/auth/oauth/CLIFlowHandler.d.ts.map +1 -1
- package/dist/lib/auth/oauth/CLIFlowHandler.js +40 -4
- package/dist/lib/auth/oauth/CLIFlowHandler.js.map +1 -1
- package/dist/lib/auth/oauth/CLIFlowHandler.mjs +40 -4
- package/dist/lib/auth/oauth/CLIFlowHandler.mjs.map +1 -1
- package/dist/lib/auth/oauth/index.d.mts +1 -1
- package/dist/lib/auth/oauth/index.d.ts +1 -1
- package/dist/lib/auth/oauth/index.d.ts.map +1 -1
- package/dist/lib/auth/oauth/index.js +2 -0
- package/dist/lib/auth/oauth/index.js.map +1 -1
- package/dist/lib/auth/oauth/index.mjs +2 -0
- package/dist/lib/auth/oauth/index.mjs.map +1 -1
- package/dist/lib/auth/oauth/web-flow.d.mts +12 -0
- package/dist/lib/auth/oauth/web-flow.d.ts +12 -0
- package/dist/lib/auth/oauth/web-flow.d.ts.map +1 -1
- package/dist/lib/auth/oauth/web-flow.js +20 -2
- package/dist/lib/auth/oauth/web-flow.js.map +1 -1
- package/dist/lib/auth/oauth/web-flow.mjs +19 -2
- package/dist/lib/auth/oauth/web-flow.mjs.map +1 -1
- package/dist/lib/core/AgentClient.d.ts.map +1 -1
- package/dist/lib/core/SingleAgentClient.d.mts +27 -1
- package/dist/lib/core/SingleAgentClient.d.ts +27 -1
- package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
- package/dist/lib/core/SingleAgentClient.js +46 -18
- package/dist/lib/core/SingleAgentClient.js.map +1 -1
- package/dist/lib/core/SingleAgentClient.mjs +46 -18
- package/dist/lib/core/SingleAgentClient.mjs.map +1 -1
- package/dist/lib/net/address-guards.d.ts.map +1 -1
- package/dist/lib/net/address-guards.js +4 -0
- package/dist/lib/net/address-guards.js.map +1 -1
- package/dist/lib/net/address-guards.mjs +4 -0
- package/dist/lib/net/address-guards.mjs.map +1 -1
- package/dist/lib/protocols/a2a.js +2 -2
- package/dist/lib/protocols/a2a.js.map +1 -1
- package/dist/lib/protocols/a2a.mjs +2 -2
- package/dist/lib/protocols/a2a.mjs.map +1 -1
- package/dist/lib/protocols/index.d.ts.map +1 -1
- package/dist/lib/protocols/index.js +28 -7
- package/dist/lib/protocols/index.js.map +1 -1
- package/dist/lib/protocols/index.mjs +28 -7
- package/dist/lib/protocols/index.mjs.map +1 -1
- package/dist/lib/protocols/mcp-modern.d.ts.map +1 -1
- package/dist/lib/protocols/mcp-modern.js +18 -5
- package/dist/lib/protocols/mcp-modern.js.map +1 -1
- package/dist/lib/protocols/mcp-modern.mjs +18 -5
- package/dist/lib/protocols/mcp-modern.mjs.map +1 -1
- package/dist/lib/protocols/mcp-tasks.d.ts.map +1 -1
- package/dist/lib/protocols/mcp-tasks.js +2 -12
- package/dist/lib/protocols/mcp-tasks.js.map +1 -1
- package/dist/lib/protocols/mcp-tasks.mjs +2 -12
- package/dist/lib/protocols/mcp-tasks.mjs.map +1 -1
- package/dist/lib/protocols/mcp.js +2 -2
- package/dist/lib/protocols/mcp.js.map +1 -1
- package/dist/lib/protocols/mcp.mjs +2 -2
- package/dist/lib/protocols/mcp.mjs.map +1 -1
- package/dist/lib/registry/types.generated.d.mts +554 -15
- package/dist/lib/registry/types.generated.d.ts +554 -15
- package/dist/lib/registry/types.generated.d.ts.map +1 -1
- package/dist/lib/registry/types.generated.js.map +1 -1
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/decisioning/account.d.mts +6 -4
- package/dist/lib/server/decisioning/account.d.ts +6 -4
- package/dist/lib/server/decisioning/account.d.ts.map +1 -1
- package/dist/lib/server/decisioning/account.js.map +1 -1
- package/dist/lib/server/decisioning/account.mjs.map +1 -1
- package/dist/lib/server/decisioning/manifest-helpers.d.mts +6 -5
- package/dist/lib/server/decisioning/manifest-helpers.d.ts +6 -5
- package/dist/lib/server/decisioning/manifest-helpers.d.ts.map +1 -1
- package/dist/lib/server/decisioning/manifest-helpers.js.map +1 -1
- package/dist/lib/server/decisioning/manifest-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.js +4 -2
- package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +4 -2
- package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/tenant-store.d.mts +26 -14
- package/dist/lib/server/decisioning/tenant-store.d.ts +26 -14
- package/dist/lib/server/decisioning/tenant-store.d.ts.map +1 -1
- package/dist/lib/server/decisioning/tenant-store.js +6 -1
- package/dist/lib/server/decisioning/tenant-store.js.map +1 -1
- package/dist/lib/server/decisioning/tenant-store.mjs +6 -1
- package/dist/lib/server/decisioning/tenant-store.mjs.map +1 -1
- package/dist/lib/server/pin-and-bind-fetch.d.mts +2 -0
- package/dist/lib/server/pin-and-bind-fetch.d.ts +2 -0
- package/dist/lib/server/pin-and-bind-fetch.d.ts.map +1 -1
- package/dist/lib/server/pin-and-bind-fetch.js +2 -0
- package/dist/lib/server/pin-and-bind-fetch.js.map +1 -1
- package/dist/lib/server/pin-and-bind-fetch.mjs +2 -0
- package/dist/lib/server/pin-and-bind-fetch.mjs.map +1 -1
- package/dist/lib/server/structured-serialize.d.ts.map +1 -1
- package/dist/lib/server/structured-serialize.js +10 -2
- package/dist/lib/server/structured-serialize.js.map +1 -1
- package/dist/lib/server/structured-serialize.mjs +10 -2
- package/dist/lib/server/structured-serialize.mjs.map +1 -1
- package/dist/lib/server/webhook-emitter.d.ts.map +1 -1
- package/dist/lib/server/webhook-emitter.js +4 -2
- package/dist/lib/server/webhook-emitter.js.map +1 -1
- package/dist/lib/server/webhook-emitter.mjs +4 -2
- package/dist/lib/server/webhook-emitter.mjs.map +1 -1
- package/dist/lib/signing/middleware.d.mts +2 -1
- package/dist/lib/signing/middleware.d.ts +2 -1
- package/dist/lib/signing/middleware.d.ts.map +1 -1
- package/dist/lib/signing/middleware.js +26 -4
- package/dist/lib/signing/middleware.js.map +1 -1
- package/dist/lib/signing/middleware.mjs +26 -4
- package/dist/lib/signing/middleware.mjs.map +1 -1
- package/dist/lib/signing/webhook-verifier.d.ts.map +1 -1
- package/dist/lib/signing/webhook-verifier.js +4 -2
- package/dist/lib/signing/webhook-verifier.js.map +1 -1
- package/dist/lib/signing/webhook-verifier.mjs +4 -2
- package/dist/lib/signing/webhook-verifier.mjs.map +1 -1
- package/dist/lib/testing/agent-tester.d.ts.map +1 -1
- package/dist/lib/testing/agent-tester.js +46 -1
- package/dist/lib/testing/agent-tester.js.map +1 -1
- package/dist/lib/testing/agent-tester.mjs +46 -1
- package/dist/lib/testing/agent-tester.mjs.map +1 -1
- package/dist/lib/types/asset-instances.d.mts +8 -6
- package/dist/lib/types/asset-instances.d.ts +8 -6
- package/dist/lib/types/asset-instances.d.ts.map +1 -1
- package/dist/lib/types/asset-instances.js.map +1 -1
- package/dist/lib/types/index.d.ts.map +1 -1
- package/dist/lib/types/index.js.map +1 -1
- package/dist/lib/types/index.mjs.map +1 -1
- package/dist/lib/utils/capabilities.d.mts +2 -0
- package/dist/lib/utils/capabilities.d.ts +2 -0
- package/dist/lib/utils/capabilities.d.ts.map +1 -1
- package/dist/lib/utils/capabilities.js +2 -1
- package/dist/lib/utils/capabilities.js.map +1 -1
- package/dist/lib/utils/capabilities.mjs +2 -1
- package/dist/lib/utils/capabilities.mjs.map +1 -1
- package/dist/lib/utils/probe-policy.d.mts +0 -16
- package/dist/lib/utils/probe-policy.d.ts +0 -16
- package/dist/lib/utils/probe-policy.d.ts.map +1 -1
- package/dist/lib/utils/probe-policy.js +15 -1
- package/dist/lib/utils/probe-policy.js.map +1 -1
- package/dist/lib/utils/probe-policy.mjs +15 -1
- package/dist/lib/utils/probe-policy.mjs.map +1 -1
- package/dist/lib/utils/redact-args.d.mts +36 -0
- package/dist/lib/utils/redact-args.d.ts +37 -0
- package/dist/lib/utils/redact-args.d.ts.map +1 -0
- package/dist/lib/utils/redact-args.js +46 -0
- package/dist/lib/utils/redact-args.js.map +1 -0
- package/dist/lib/utils/redact-args.mjs +22 -0
- package/dist/lib/utils/redact-args.mjs.map +1 -0
- package/dist/lib/v2/projection/creative-delivery.js +1 -5
- package/dist/lib/v2/projection/creative-delivery.js.map +1 -1
- package/dist/lib/v2/projection/creative-delivery.mjs +1 -5
- package/dist/lib/v2/projection/creative-delivery.mjs.map +1 -1
- package/dist/lib/validation/index.d.mts +15 -1
- package/dist/lib/validation/index.d.ts +15 -1
- package/dist/lib/validation/index.d.ts.map +1 -1
- package/dist/lib/validation/index.js +4 -8
- package/dist/lib/validation/index.js.map +1 -1
- package/dist/lib/validation/index.mjs +4 -8
- package/dist/lib/validation/index.mjs.map +1 -1
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.js.map +1 -1
- package/dist/lib/version.mjs +3 -3
- package/dist/lib/version.mjs.map +1 -1
- package/examples/hello_seller_adapter_multi_tenant.ts +7 -0
- package/package.json +3 -2
- package/skills/build-holdco-agent/SKILL.md +19 -0
- 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
|
-
*
|
|
26
|
-
*
|
|
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 = "
|
|
39
|
-
args = ["
|
|
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, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
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\">✓</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\">✗</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, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\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\">✓</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\">✗</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, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\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":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAGH,YAAY,EACV,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,0BAA0B,EAC1B,mBAAmB,EACnB,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAEjB,OAAO,EACL,uBAAuB,EACvB,UAAU,EACV,mBAAmB,EACnB,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,eAAe,EACf,iBAAiB,GAClB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,cAAc,EAAE,KAAK,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAE,yBAAyB,EAAE,KAAK,+BAA+B,EAAE,MAAM,6BAA6B,CAAC;AAM9G,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,YAAY,EACZ,wBAAwB,EACxB,yBAAyB,EACzB,kBAAkB,EAClB,kBAAkB,EAClB,8BAA8B,EAC9B,4BAA4B,EAC5B,iCAAiC,EACjC,uBAAuB,EACvB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,GAC3B,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAMtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGpF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,WAAW,EAClB,OAAO,CAAC,EAAE;IACR,oCAAoC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,cAAc,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC9C,8BAA8B;IAC9B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,GACA,gBAAgB,CAsBlB;AAED;;;;;;;;;GASG;AACH,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,WAAW,EAClB,OAAO,CAAC,EAAE;IACR,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wFAAwF;IACxF,cAAc,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC9C,4DAA4D;IAC5D,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,GACA,gBAAgB,CAgBlB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CASvD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAa/D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAIzD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAO5E;AAGD,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,2BAA2B,EAC3B,KAAK,aAAa,EAClB,KAAK,gBAAgB,GACtB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,qBAAqB,EACrB,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,GACzB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,gBAAgB,EAChB,6BAA6B,EAC7B,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,GACzB,MAAM,YAAY,CAAC;AAKpB,OAAO,EACL,uBAAuB,EACvB,iCAAiC,EACjC,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,4BAA4B,GAClC,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,sBAAsB,EAAE,KAAK,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAKtF,OAAO,EACL,yBAAyB,EACzB,6BAA6B,EAC7B,8BAA8B,EAC9B,KAAK,gCAAgC,EACrC,KAAK,8BAA8B,GACpC,MAAM,yBAAyB,CAAC;AAIjC,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAI3B,YAAY,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AAIpE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAK3F,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,iDAAiD,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/auth/oauth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAGH,YAAY,EACV,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,0BAA0B,EAC1B,mBAAmB,EACnB,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAEjB,OAAO,EACL,uBAAuB,EACvB,UAAU,EACV,mBAAmB,EACnB,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,eAAe,EACf,iBAAiB,GAClB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,cAAc,EAAE,KAAK,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAE,yBAAyB,EAAE,KAAK,+BAA+B,EAAE,MAAM,6BAA6B,CAAC;AAM9G,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,YAAY,EACZ,wBAAwB,EACxB,yBAAyB,EACzB,kBAAkB,EAClB,2BAA2B,EAC3B,kBAAkB,EAClB,8BAA8B,EAC9B,4BAA4B,EAC5B,iCAAiC,EACjC,uBAAuB,EACvB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,GAC3B,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAMtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGpF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,WAAW,EAClB,OAAO,CAAC,EAAE;IACR,oCAAoC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,cAAc,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC9C,8BAA8B;IAC9B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,GACA,gBAAgB,CAsBlB;AAED;;;;;;;;;GASG;AACH,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,WAAW,EAClB,OAAO,CAAC,EAAE;IACR,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wFAAwF;IACxF,cAAc,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC9C,4DAA4D;IAC5D,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,GACA,gBAAgB,CAgBlB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CASvD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAa/D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAIzD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAO5E;AAGD,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,2BAA2B,EAC3B,KAAK,aAAa,EAClB,KAAK,gBAAgB,GACtB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,qBAAqB,EACrB,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,GACzB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,gBAAgB,EAChB,6BAA6B,EAC7B,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,GACzB,MAAM,YAAY,CAAC;AAKpB,OAAO,EACL,uBAAuB,EACvB,iCAAiC,EACjC,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,4BAA4B,GAClC,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,sBAAsB,EAAE,KAAK,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAKtF,OAAO,EACL,yBAAyB,EACzB,6BAA6B,EAC7B,8BAA8B,EAC9B,KAAK,gCAAgC,EACrC,KAAK,8BAA8B,GACpC,MAAM,yBAAyB,CAAC;AAIjC,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAI3B,YAAY,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AAIpE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAK3F,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,iDAAiD,CAAC"}
|
|
@@ -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
|
|
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,
|