{"record":{"id":"a91f680ea403e09f","repo":"can1357/oh-my-pi","slug":"oauth-redirect-uri-must-use-http-or-https","errorCode":null,"errorMessage":"OAuth redirect URI must use http or https","messagePattern":"OAuth redirect URI must use http or https","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/mcp/oauth-flow.ts","lineNumber":143,"sourceCode":"\t\treturn undefined;\n\t}\n}\n\nfunction isLoopbackHostname(hostname: string): boolean {\n\treturn hostname === \"localhost\" || hostname === \"127.0.0.1\";\n}\n\nfunction resolveRedirectUri(redirectUri: string | undefined): string | undefined {\n\tconst configured = redirectUri;\n\tconst trimmed = configured?.trim();\n\tif (!trimmed) return undefined;\n\tif (trimmed !== configured) {\n\t\tthrow new Error(\"OAuth redirect URI must not include surrounding whitespace\");\n\t}\n\n\tconst parsed = new URL(configured);\n\tif (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n\t\tthrow new Error(\"OAuth redirect URI must use http or https\");\n\t}\n\treturn configured;\n}\n\nfunction parseRedirectUri(redirectUri: string | undefined): URL | undefined {\n\treturn redirectUri ? new URL(redirectUri) : undefined;\n}\n\nfunction getUriPort(uri: URL): number {\n\tif (uri.port !== \"\") return Number(uri.port);\n\treturn uri.protocol === \"https:\" ? 443 : 80;\n}\n\nfunction validateRedirectConfig(config: MCPOAuthConfig, redirectUri: string | undefined): void {\n\tconst parsed = parseRedirectUri(redirectUri);\n\tif (parsed?.protocol !== \"https:\" || !isLoopbackHostname(parsed.hostname)) {\n\t\treturn;\n\t}","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/mcp/oauth-flow.ts#L125-L161","documentation":"resolveRedirectUri enforces that an OAuth redirect URI uses the http or https scheme. After parsing the configured URI, any other protocol (file:, ws:, custom schemes, or a missing/typo'd scheme) is rejected, since OAuth redirect URIs must be valid web URLs that the local callback listener or a TLS-terminated endpoint can serve.","triggerScenarios":"Configuring oauth.redirectUri with a non-http(s) scheme — e.g. \"localhost:1455/callback\" (no scheme), \"ftp://...\", \"file://...\", or a typo like \"htp://localhost:1455\" — then starting the MCP OAuth authorization flow.","commonSituations":"Omitting the scheme and assuming localhost defaults to http; typos in the scheme; copy-pasting an app-specific scheme (myapp://callback) intended for a different client type; misconfigured redirect in a shared config file.","solutions":["Prefix the redirect URI with http:// or https:// (use http://localhost or http://127.0.0.1 for local loopback callbacks)","Fix the scheme typo if the URL was mistyped (htp:/htt:/htps:)","If you need a custom app scheme, register it with your provider and check the library docs for explicit support rather than forcing it into redirectUri"],"exampleFix":"// before\n\"redirectUri\": \"localhost:1455/auth/callback\"\n// after\n\"redirectUri\": \"http://localhost:1455/auth/callback\"","handlingStrategy":"validation","validationCode":"const uri = config.oauth?.redirectUri;\nif (uri != null) {\n  const p = new URL(uri); // throws on unparseable\n  if (p.protocol !== 'http:' && p.protocol !== 'https:') {\n    throw new Error(`redirectUri must be http(s), got ${p.protocol}`);\n  }\n}","typeGuard":"function isHttpUrl(s) {\n  try { const p = new URL(s); return p.protocol === 'http:' || p.protocol === 'https:'; }\n  catch { return false; }\n}","tryCatchPattern":"try {\n  startOAuthFlow(config);\n} catch (e) {\n  if (e.message.includes('must use http or https')) {\n    throw new Error(`Fix oauth.redirectUri scheme: '${config.oauth.redirectUri}' needs http:// or https://`);\n  } else throw e;\n}","preventionTips":["Always write the full scheme, even for localhost","For local development use http://localhost:<port> or http://127.0.0.1:<port>","Register the exact URI (scheme included) with your OAuth provider","Validate URLs with new URL() at config load"],"tags":["oauth","configuration","validation","url"],"backgroundTag":"invalid-redirect-uri","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}