Unified · Split
| @@ -135,17 +135,6 @@ · 134 unmodified lines | |||
| 135 | "bun-types": "catalog:", | 135 | "bun-types": "catalog:", |
| 136 | }, | 136 | }, |
| 137 | }, | 137 | }, |
| 138 | "packages/auth/oauth2": { | ||
| 139 | "name": "@executor/auth-oauth2", | ||
| 140 | "version": "0.0.0", | ||
| 141 | "dependencies": { | ||
| 142 | "effect": "catalog:", | ||
| 143 | }, | ||
| 144 | "devDependencies": { | ||
| 145 | "@types/node": "catalog:", | ||
| 146 | "bun-types": "catalog:", | ||
| 147 | }, | ||
| 148 | }, | ||
| 149 | "packages/clients/react": { | 138 | "packages/clients/react": { |
| 150 | "name": "@executor/react", | 139 | "name": "@executor/react", |
| 151 | "version": "0.0.0", | 140 | "version": "0.0.0", |
| @@ -351,8 +340,6 @@ · 199 unmodified lines | |||
| 351 | "dependencies": { | 340 | "dependencies": { |
| 352 | "@effect/platform": "catalog:", | 341 | "@effect/platform": "catalog:", |
| 353 | "@effect/platform-node": "catalog:", | 342 | "@effect/platform-node": "catalog:", |
| 354 | "@executor/auth-mcp-oauth": "workspace:*", | ||
| 355 | "@executor/auth-oauth2": "workspace:*", | ||
| 356 | "@executor/codemode-core": "workspace:*", | 343 | "@executor/codemode-core": "workspace:*", |
| 357 | "@executor/ir": "workspace:*", | 344 | "@executor/ir": "workspace:*", |
| 358 | "@executor/runtime-deno-subprocess": "workspace:*", | 345 | "@executor/runtime-deno-subprocess": "workspace:*", |
| @@ -436,7 +423,6 @@ · 77 unmodified lines | |||
| 436 | "name": "@executor/source-core", | 423 | "name": "@executor/source-core", |
| 437 | "version": "0.0.0", | 424 | "version": "0.0.0", |
| 438 | "dependencies": { | 425 | "dependencies": { |
| 439 | "@executor/auth-oauth2": "workspace:*", | ||
| 440 | "@executor/codemode-core": "workspace:*", | 426 | "@executor/codemode-core": "workspace:*", |
| 441 | "@executor/ir": "workspace:*", | 427 | "@executor/ir": "workspace:*", |
| 442 | "@modelcontextprotocol/sdk": "^1.26.0", | 428 | "@modelcontextprotocol/sdk": "^1.26.0", |
| @@ -482,7 +468,6 @@ · 39 unmodified lines | |||
| 482 | "version": "0.0.0", | 468 | "version": "0.0.0", |
| 483 | "dependencies": { | 469 | "dependencies": { |
| 484 | "@effect/platform": "catalog:", | 470 | "@effect/platform": "catalog:", |
| 485 | "@executor/auth-oauth2": "workspace:*", | ||
| 486 | "@executor/codemode-core": "workspace:*", | 471 | "@executor/codemode-core": "workspace:*", |
| 487 | "@executor/ir": "workspace:*", | 472 | "@executor/ir": "workspace:*", |
| 488 | "@executor/platform-sdk": "workspace:*", | 473 | "@executor/platform-sdk": "workspace:*", |
| @@ -900,8 +885,6 @@ · 411 unmodified lines | |||
| 900 | 885 | ||
| 901 | "@executor/auth-mcp-oauth": ["@executor/auth-mcp-oauth@workspace:packages/auth/mcp-oauth"], | 886 | "@executor/auth-mcp-oauth": ["@executor/auth-mcp-oauth@workspace:packages/auth/mcp-oauth"], |
| 902 | 887 | ||
| 903 | "@executor/auth-oauth2": ["@executor/auth-oauth2@workspace:packages/auth/oauth2"], | ||
| 904 | |||
| 905 | "@executor/codemode-core": ["@executor/codemode-core@workspace:packages/kernel/core"], | 888 | "@executor/codemode-core": ["@executor/codemode-core@workspace:packages/kernel/core"], |
| 906 | 889 | ||
| 907 | "@executor/docs": ["@executor/docs@workspace:apps/docs"], | 890 | "@executor/docs": ["@executor/docs@workspace:apps/docs"], |
| @@ -1,22 +0,0 @@ | |||
| 1 | { | ||
| 2 | "name": "@executor/auth-oauth2", | ||
| 3 | "private": true, | ||
| 4 | "type": "module", | ||
| 5 | "exports": { | ||
| 6 | ".": "./src/index.ts" | ||
| 7 | }, | ||
| 8 | "files": [ | ||
| 9 | "src" | ||
| 10 | ], | ||
| 11 | "scripts": { | ||
| 12 | "typecheck": "bunx tsc --noEmit -p tsconfig.json" | ||
| 13 | }, | ||
| 14 | "dependencies": { | ||
| 15 | "effect": "catalog:" | ||
| 16 | }, | ||
| 17 | "devDependencies": { | ||
| 18 | "@types/node": "catalog:", | ||
| 19 | "bun-types": "catalog:" | ||
| 20 | }, | ||
| 21 | "version": "0.0.0" | ||
| 22 | } | ||
| @@ -1,19 +0,0 @@ | |||
| 1 | { | ||
| 2 | "compilerOptions": { | ||
| 3 | "target": "ES2022", | ||
| 4 | "module": "ESNext", | ||
| 5 | "moduleResolution": "Bundler", | ||
| 6 | "strict": true, | ||
| 7 | "skipLibCheck": true, | ||
| 8 | "noEmit": true, | ||
| 9 | "lib": ["ES2022"], | ||
| 10 | "types": ["bun-types", "node"] | ||
| 11 | }, | ||
| 12 | "include": [ | ||
| 13 | "src/**/*.ts", | ||
| 14 | "src/**/*.d.ts" | ||
| 15 | ], | ||
| 16 | "exclude": [ | ||
| 17 | "src/**/*.test.ts" | ||
| 18 | ] | ||
| 19 | } | ||
| @@ -27,8 +27,6 @@ · 26 unmodified lines | |||
| 27 | "dependencies": { | 27 | "dependencies": { |
| 28 | "@effect/platform": "catalog:", | 28 | "@effect/platform": "catalog:", |
| 29 | "@effect/platform-node": "catalog:", | 29 | "@effect/platform-node": "catalog:", |
| 30 | "@executor/auth-mcp-oauth": "workspace:*", | ||
| 31 | "@executor/auth-oauth2": "workspace:*", | ||
| 32 | "@executor/codemode-core": "workspace:*", | 30 | "@executor/codemode-core": "workspace:*", |
| 33 | "@executor/ir": "workspace:*", | 31 | "@executor/ir": "workspace:*", |
| 34 | "@executor/runtime-deno-subprocess": "workspace:*", | 32 | "@executor/runtime-deno-subprocess": "workspace:*", |
| @@ -1 +0,0 @@ | |||
| 1 | export * from "@executor/auth-mcp-oauth"; | ||
| @@ -1,110 +0,0 @@ | |||
| 1 | import { | ||
| 2 | createServer, | ||
| 3 | } from "node:http"; | ||
| 4 | |||
| 5 | import { | ||
| 6 | describe, | ||
| 7 | expect, | ||
| 8 | it, | ||
| 9 | } from "@effect/vitest"; | ||
| 10 | import * as Effect from "effect/Effect"; | ||
| 11 | |||
| 12 | import { | ||
| 13 | startOauthLoopbackRedirectServer, | ||
| 14 | } from "./oauth-loopback"; | ||
| 15 | |||
| 16 | const toError = (cause: unknown): Error => | ||
| 17 | cause instanceof Error ? cause : new Error(String(cause)); | ||
| 18 | |||
| 19 | const makeCompletionServer = Effect.acquireRelease( | ||
| 20 | Effect.tryPromise({ | ||
| 21 | try: () => | ||
| 22 | new Promise<{ | ||
| 23 | completionUrl: string; | ||
| 24 | requests: string[]; | ||
| 25 | server: ReturnType<typeof createServer>; | ||
| 26 | }>((resolve, reject) => { | ||
| 27 | const requests: string[] = []; | ||
| 28 | const server = createServer((request, response) => { | ||
| 29 | requests.push(request.url ?? "/"); | ||
| 30 | response.statusCode = 200; | ||
| 31 | response.end("ok"); | ||
| 32 | }); | ||
| 33 | |||
| 34 | server.listen(0, "127.0.0.1", (error?: Error) => { | ||
| 35 | if (error) { | ||
| 36 | reject(error); | ||
| 37 | return; | ||
| 38 | } | ||
| 39 | |||
| 40 | const address = server.address(); | ||
| 41 | if (!address || typeof address === "string") { | ||
| 42 | reject(new Error("Failed to resolve completion server address")); | ||
| 43 | return; | ||
| 44 | } | ||
| 45 | |||
| 46 | resolve({ | ||
| 47 | completionUrl: `http://127.0.0.1:${address.port}/oauth/complete?sessionId=test-session`, | ||
| 48 | requests, | ||
| 49 | server, | ||
| 50 | }); | ||
| 51 | }); | ||
| 52 | }), | ||
| 53 | catch: toError, | ||
| 54 | }), | ||
| 55 | ({ server }) => | ||
| 56 | Effect.tryPromise({ | ||
| 57 | try: () => | ||
| 58 | new Promise<void>((resolve, reject) => { | ||
| 59 | server.close((error) => { | ||
| 60 | if (error) { | ||
| 61 | reject(error); | ||
| 62 | return; | ||
| 63 | } | ||
| 64 | resolve(); | ||
| 65 | }); | ||
| 66 | }), | ||
| 67 | catch: toError, | ||
| 68 | }), | ||
| 69 | ); | ||
| 70 | |||
| 71 | const withCompletionServer = <T>( | ||
| 72 | handler: (input: { | ||
| 73 | completionUrl: string; | ||
| 74 | requests: string[]; | ||
| 75 | }) => Effect.Effect<T, Error, never>, | ||
| 76 | ) => Effect.flatMap(makeCompletionServer, handler); | ||
| 77 | |||
| 78 | describe("oauth-loopback", () => { | ||
| 79 | it.scoped( | ||
| 80 | "redirects loopback callbacks to the app completion URL with query params intact", | ||
| 81 | () => | ||
| 82 | withCompletionServer(({ completionUrl, requests }) => | ||
| 83 | Effect.gen(function* () { | ||
| 84 | const receiver = yield* Effect.acquireRelease( | ||
| 85 | startOauthLoopbackRedirectServer({ | ||
| 86 | completionUrl, | ||
| 87 | }), | ||
| 88 | (server) => server.close, | ||
| 89 | ); | ||
| 90 | |||
| 91 | const response = yield* Effect.tryPromise({ | ||
| 92 | try: () => | ||
| 93 | fetch( | ||
| 94 | `${receiver.redirectUri}?state=oauth-state&code=oauth-code`, | ||
| 95 | { | ||
| 96 | redirect: "follow", | ||
| 97 | signal: AbortSignal.timeout(10_000), | ||
| 98 | }, | ||
| 99 | ), | ||
| 100 | catch: toError, | ||
| 101 | }); | ||
| 102 | |||
| 103 | expect(response.ok).toBe(true); | ||
| 104 | expect(requests).toEqual([ | ||
| 105 | "/oauth/complete?sessionId=test-session&state=oauth-state&code=oauth-code", | ||
| 106 | ]); | ||
| 107 | }), | ||
| 108 | ), | ||
| 109 | ); | ||
| 110 | }); | ||
| @@ -1,106 +0,0 @@ | |||
| 1 | import { | ||
| 2 | createServer, | ||
| 3 | } from "node:http"; | ||
| 4 | |||
| 5 | import * as Effect from "effect/Effect"; | ||
| 6 | |||
| 7 | const DEFAULT_LOOPBACK_TIMEOUT_MS = 10 * 60_000; | ||
| 8 | |||
| 9 | export type OauthLoopbackRedirectServer = { | ||
| 10 | redirectUri: string; | ||
| 11 | close: Effect.Effect<void, Error, never>; | ||
| 12 | }; | ||
| 13 | |||
| 14 | const closeServer = ( | ||
| 15 | server: ReturnType<typeof createServer>, | ||
| 16 | ): Promise<void> => | ||
| 17 | new Promise<void>((resolve, reject) => { | ||
| 18 | server.close((error) => { | ||
| 19 | if (error) { | ||
| 20 | reject(error); | ||
| 21 | return; | ||
| 22 | } | ||
| 23 | resolve(); | ||
| 24 | }); | ||
| 25 | }); | ||
| 26 | |||
| 27 | export const startOauthLoopbackRedirectServer = (input: { | ||
| 28 | completionUrl: string; | ||
| 29 | publicHost?: "localhost" | "127.0.0.1"; | ||
| 30 | listenHost?: "127.0.0.1"; | ||
| 31 | timeoutMs?: number; | ||
| 32 | }): Effect.Effect<OauthLoopbackRedirectServer, Error, never> => | ||
| 33 | Effect.tryPromise({ | ||
| 34 | try: () => | ||
| 35 | new Promise<OauthLoopbackRedirectServer>((resolve, reject) => { | ||
| 36 | const publicHost = input.publicHost ?? "127.0.0.1"; | ||
| 37 | const listenHost = input.listenHost ?? "127.0.0.1"; | ||
| 38 | const completionUrl = new URL(input.completionUrl); | ||
| 39 | const server = createServer((request, response) => { | ||
| 40 | try { | ||
| 41 | const requestUrl = new URL( | ||
| 42 | request.url ?? "/", | ||
| 43 | `http://${publicHost}`, | ||
| 44 | ); | ||
| 45 | const redirectUrl = new URL(completionUrl.toString()); | ||
| 46 | |||
| 47 | for (const [key, value] of requestUrl.searchParams.entries()) { | ||
| 48 | redirectUrl.searchParams.set(key, value); | ||
| 49 | } | ||
| 50 | |||
| 51 | response.statusCode = 302; | ||
| 52 | response.setHeader("cache-control", "no-store"); | ||
| 53 | response.setHeader("location", redirectUrl.toString()); | ||
| 54 | response.end(); | ||
| 55 | } catch (cause) { | ||
| 56 | const error = cause instanceof Error ? cause : new Error(String(cause)); | ||
| 57 | response.statusCode = 500; | ||
| 58 | response.setHeader("content-type", "text/plain; charset=utf-8"); | ||
| 59 | response.end(`OAuth redirect failed: ${error.message}`); | ||
| 60 | } finally { | ||
| 61 | void closeServer(server).catch(() => {}); | ||
| 62 | } | ||
| 63 | }); | ||
| 64 | |||
| 65 | let timeout: NodeJS.Timeout | null = null; | ||
| 66 | const cleanup = (): Promise<void> => { | ||
| 67 | if (timeout !== null) { | ||
| 68 | clearTimeout(timeout); | ||
| 69 | timeout = null; | ||
| 70 | } | ||
| 71 | return closeServer(server).catch(() => undefined); | ||
| 72 | }; | ||
| 73 | |||
| 74 | server.once("error", (cause) => { | ||
| 75 | reject( | ||
| 76 | cause instanceof Error ? cause : new Error(String(cause)), | ||
| 77 | ); | ||
| 78 | }); | ||
| 79 | |||
| 80 | server.listen(0, listenHost, () => { | ||
| 81 | const address = server.address(); | ||
| 82 | if (!address || typeof address === "string") { | ||
| 83 | reject(new Error("Failed to resolve OAuth loopback port")); | ||
| 84 | return; | ||
| 85 | } | ||
| 86 | |||
| 87 | timeout = setTimeout(() => { | ||
| 88 | void cleanup(); | ||
| 89 | }, input.timeoutMs ?? DEFAULT_LOOPBACK_TIMEOUT_MS); | ||
| 90 | if (typeof timeout.unref === "function") { | ||
| 91 | timeout.unref(); | ||
| 92 | } | ||
| 93 | |||
| 94 | resolve({ | ||
| 95 | redirectUri: `http://${publicHost}:${address.port}`, | ||
| 96 | close: Effect.tryPromise({ | ||
| 97 | try: cleanup, | ||
| 98 | catch: (cause) => | ||
| 99 | cause instanceof Error ? cause : new Error(String(cause)), | ||
| 100 | }), | ||
| 101 | }); | ||
| 102 | }); | ||
| 103 | }), | ||
| 104 | catch: (cause) => | ||
| 105 | cause instanceof Error ? cause : new Error(String(cause)), | ||
| 106 | }); | ||
| @@ -1 +0,0 @@ | |||
| 1 | export * from "@executor/auth-oauth2"; | ||
| @@ -12,7 +12,6 @@ · 11 unmodified lines | |||
| 12 | "typecheck": "bunx tsc --noEmit -p tsconfig.json" | 12 | "typecheck": "bunx tsc --noEmit -p tsconfig.json" |
| 13 | }, | 13 | }, |
| 14 | "dependencies": { | 14 | "dependencies": { |
| 15 | "@executor/auth-oauth2": "workspace:*", | ||
| 16 | "@executor/codemode-core": "workspace:*", | 15 | "@executor/codemode-core": "workspace:*", |
| 17 | "@executor/ir": "workspace:*", | 16 | "@executor/ir": "workspace:*", |
| 18 | "@modelcontextprotocol/sdk": "^1.26.0", | 17 | "@modelcontextprotocol/sdk": "^1.26.0", |
| @@ -1,12 +1,6 @@ | |||
| 1 | import * as Effect from "effect/Effect"; | 1 | import * as Effect from "effect/Effect"; |
| 2 | import * as Schema from "effect/Schema"; | 2 | import * as Schema from "effect/Schema"; |
| 3 | 3 | ||
| 4 | import { | ||
| 5 | buildOAuth2AuthorizationUrl, | ||
| 6 | createPkceCodeVerifier, | ||
| 7 | exchangeOAuth2AuthorizationCode, | ||
| 8 | refreshOAuth2AccessToken, | ||
| 9 | } from "@executor/auth-oauth2"; | ||
| 10 | import { | 4 | import { |
| 11 | createCatalogImportMetadata, | 5 | createCatalogImportMetadata, |
| 12 | createSourceCatalogSyncResult, | 6 | createSourceCatalogSyncResult, |
| @@ -58,6 +52,12 @@ import { · 45 unmodified lines | |||
| 58 | type GoogleDiscoveryToolManifest, | 52 | type GoogleDiscoveryToolManifest, |
| 59 | type GoogleDiscoveryToolProviderData, | 53 | type GoogleDiscoveryToolProviderData, |
| 60 | } from "./types"; | 54 | } from "./types"; |
| 55 | import { | ||
| 56 | buildOAuth2AuthorizationUrl, | ||
| 57 | createPkceCodeVerifier, | ||
| 58 | exchangeOAuth2AuthorizationCode, | ||
| 59 | refreshOAuth2AccessToken, | ||
| 60 | } from "./oauth2"; | ||
| 61 | 61 | ||
| 62 | const decodeStoredSourceData = Schema.decodeUnknownSync( | 62 | const decodeStoredSourceData = Schema.decodeUnknownSync( |
| 63 | GoogleDiscoveryStoredSourceDataSchema, | 63 | GoogleDiscoveryStoredSourceDataSchema, |
| @@ -42,7 +42,10 @@ export const buildOAuth2AuthorizationUrl = (input: { · 41 unmodified lines | |||
| 42 | url.searchParams.set("scope", input.scopes.join(" ")); | 42 | url.searchParams.set("scope", input.scopes.join(" ")); |
| 43 | url.searchParams.set("state", input.state); | 43 | url.searchParams.set("state", input.state); |
| 44 | url.searchParams.set("code_challenge_method", "S256"); | 44 | url.searchParams.set("code_challenge_method", "S256"); |
| 45 | url.searchParams.set("code_challenge", createPkceCodeChallenge(input.codeVerifier)); | 45 | url.searchParams.set( |
| 46 | "code_challenge", | ||
| 47 | createPkceCodeChallenge(input.codeVerifier), | ||
| 48 | ); | ||
| 46 | 49 | ||
| 47 | for (const [key, value] of Object.entries(input.extraParams ?? {})) { | 50 | for (const [key, value] of Object.entries(input.extraParams ?? {})) { |
| 48 | url.searchParams.set(key, value); | 51 | url.searchParams.set(key, value); |
| @@ -51,17 +54,23 @@ export const buildOAuth2AuthorizationUrl = (input: { · 2 unmodified lines | |||
| 51 | return url.toString(); | 54 | return url.toString(); |
| 52 | }; | 55 | }; |
| 53 | 56 | ||
| 54 | const parseOAuth2TokenResponse = async (response: Response): Promise<OAuth2TokenResponse> => { | 57 | const parseOAuth2TokenResponse = async ( |
| 58 | response: Response, | ||
| 59 | ): Promise<OAuth2TokenResponse> => { | ||
| 55 | const rawText = await response.text(); | 60 | const rawText = await response.text(); |
| 56 | let parsed: unknown; | 61 | let parsed: unknown; |
| 57 | try { | 62 | try { |
| 58 | parsed = JSON.parse(rawText); | 63 | parsed = JSON.parse(rawText); |
| 59 | } catch { | 64 | } catch { |
| 60 | throw new Error(`OAuth token endpoint returned non-JSON response (${response.status})`); | 65 | throw new Error( |
| 66 | `OAuth token endpoint returned non-JSON response (${response.status})`, | ||
| 67 | ); | ||
| 61 | } | 68 | } |
| 62 | 69 | ||
| 63 | if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) { | 70 | if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) { |
| 64 | throw new Error(`OAuth token endpoint returned invalid JSON payload (${response.status})`); | 71 | throw new Error( |
| 72 | `OAuth token endpoint returned invalid JSON payload (${response.status})`, | ||
| 73 | ); | ||
| 65 | } | 74 | } |
| 66 | 75 | ||
| 67 | const record = parsed as Record<string, unknown>; | 76 | const record = parsed as Record<string, unknown>; |
| @@ -72,7 +81,8 @@ const parseOAuth2TokenResponse = async (response: Response): Promise<OAuth2Token · 4 unmodified lines | |||
| 72 | 81 | ||
| 73 | if (!response.ok) { | 82 | if (!response.ok) { |
| 74 | const description = | 83 | const description = |
| 75 | typeof record.error_description === "string" && record.error_description.length > 0 | 84 | typeof record.error_description === "string" |
| 85 | && record.error_description.length > 0 | ||
| 76 | ? record.error_description | 86 | ? record.error_description |
| 77 | : typeof record.error === "string" && record.error.length > 0 | 87 | : typeof record.error === "string" && record.error.length > 0 |
| 78 | ? record.error | 88 | ? record.error |
| @@ -86,8 +96,12 @@ const parseOAuth2TokenResponse = async (response: Response): Promise<OAuth2Token · 7 unmodified lines | |||
| 86 | 96 | ||
| 87 | return { | 97 | return { |
| 88 | access_token: accessToken, | 98 | access_token: accessToken, |
| 89 | token_type: typeof record.token_type === "string" ? record.token_type : undefined, | 99 | token_type: |
| 90 | refresh_token: typeof record.refresh_token === "string" ? record.refresh_token : undefined, | 100 | typeof record.token_type === "string" ? record.token_type : undefined, |
| 101 | refresh_token: | ||
| 102 | typeof record.refresh_token === "string" | ||
| 103 | ? record.refresh_token | ||
| 104 | : undefined, | ||
| 91 | expires_in: typeof record.expires_in === "number" | 105 | expires_in: typeof record.expires_in === "number" |
| 92 | ? record.expires_in | 106 | ? record.expires_in |
| 93 | : typeof record.expires_in === "string" | 107 | : typeof record.expires_in === "string" |
| @@ -137,7 +151,10 @@ export const exchangeOAuth2AuthorizationCode = (input: { · 43 unmodified lines | |||
| 137 | code: input.code, | 151 | code: input.code, |
| 138 | }); | 152 | }); |
| 139 | 153 | ||
| 140 | if (input.clientAuthentication === "client_secret_post" && input.clientSecret) { | 154 | if ( |
| 155 | input.clientAuthentication === "client_secret_post" | ||
| 156 | && input.clientSecret | ||
| 157 | ) { | ||
| 141 | body.set("client_secret", input.clientSecret); | 158 | body.set("client_secret", input.clientSecret); |
| 142 | } | 159 | } |
| 143 | 160 | ||
| @@ -162,7 +179,10 @@ export const refreshOAuth2AccessToken = (input: { · 18 unmodified lines | |||
| 162 | refresh_token: input.refreshToken, | 179 | refresh_token: input.refreshToken, |
| 163 | }); | 180 | }); |
| 164 | 181 | ||
| 165 | if (input.clientAuthentication === "client_secret_post" && input.clientSecret) { | 182 | if ( |
| 183 | input.clientAuthentication === "client_secret_post" | ||
| 184 | && input.clientSecret | ||
| 185 | ) { | ||
| 166 | body.set("client_secret", input.clientSecret); | 186 | body.set("client_secret", input.clientSecret); |
| 167 | } | 187 | } |
| 168 | 188 | ||
| @@ -13,7 +13,6 @@ · 12 unmodified lines | |||
| 13 | }, | 13 | }, |
| 14 | "dependencies": { | 14 | "dependencies": { |
| 15 | "@effect/platform": "catalog:", | 15 | "@effect/platform": "catalog:", |
| 16 | "@executor/auth-oauth2": "workspace:*", | ||
| 17 | "@executor/codemode-core": "workspace:*", | 16 | "@executor/codemode-core": "workspace:*", |
| 18 | "@executor/ir": "workspace:*", | 17 | "@executor/ir": "workspace:*", |
| 19 | "@executor/platform-sdk": "workspace:*", | 18 | "@executor/platform-sdk": "workspace:*", |