| 290 | |
| 291 | // Default to prod config, override with test/staging if enabled |
| 292 | export function getOauthConfig(): OauthConfig { |
| 293 | let config: OauthConfig = (() => { |
| 294 | switch (getOauthConfigType()) { |
| 295 | case 'local': |
| 296 | return getLocalOauthConfig() |
| 297 | case 'prod': |
| 298 | return PROD_OAUTH_CONFIG |
| 299 | } |
| 300 | })() |
| 301 | |
| 302 | // Allow overriding all OAuth URLs to point to an approved FedStart deployment. |
| 303 | // Only allowlisted base URLs are accepted to prevent credential leakage. |
| 304 | const oauthBaseUrl = process.env.CLAUDE_CODE_CUSTOM_OAUTH_URL |
| 305 | if (oauthBaseUrl) { |
| 306 | const base = oauthBaseUrl.replace(/\/$/, '') |
| 307 | if (!ALLOWED_OAUTH_BASE_URLS.includes(base)) { |
| 308 | throw new Error( |
| 309 | 'Custom OAuth URL override is not an approved endpoint (CLAUDE_CODE_CUSTOM_OAUTH_URL).', |
| 310 | ) |
| 311 | } |
| 312 | config = { |
| 313 | ...config, |
| 314 | BASE_API_URL: base, |
| 315 | CONSOLE_AUTHORIZE_URL: `${base}/oauth/authorize`, |
| 316 | CLAUDE_AI_AUTHORIZE_URL: `${base}/oauth/authorize`, |
| 317 | CLAUDE_AI_ORIGIN: base, |
| 318 | TOKEN_URL: `${base}/oauth/token`, |
| 319 | API_KEY_URL: `${base}/api/oauth/ncode/create_api_key`, |
| 320 | ROLES_URL: `${base}/api/oauth/ncode/roles`, |
| 321 | CONSOLE_SUCCESS_URL: `${base}/oauth/code/success?app=noumena-code`, |
| 322 | CLAUDEAI_SUCCESS_URL: `${base}/oauth/code/success?app=noumena-code`, |
| 323 | MANUAL_REDIRECT_URL: `${base}/oauth/code/callback`, |
| 324 | OAUTH_FILE_SUFFIX: '-custom-oauth', |
| 325 | } |
| 326 | } |
| 327 | |
| 328 | // Allow CLIENT_ID override via environment variable (e.g., for Xcode integration) |
| 329 | const clientIdOverride = process.env.CLAUDE_CODE_OAUTH_CLIENT_ID |
| 330 | if (clientIdOverride) { |
| 331 | config = { |
| 332 | ...config, |
| 333 | CLIENT_ID: clientIdOverride, |
| 334 | } |
| 335 | } |
| 336 | |
| 337 | return config |
| 338 | } |