π File detail
constants/oauth.ts
π§© .tsπ 235 linesπΎ 8,970 bytesπ text
β Back to All Filesπ― Use case
This file lives under βconstants/β, which covers static strings, built-in prompts, spinners, and style constants. On the API surface it exposes fileSuffixForOauthConfig, CLAUDE_AI_INFERENCE_SCOPE, CLAUDE_AI_PROFILE_SCOPE, OAUTH_BETA_HEADER, and CONSOLE_OAUTH_SCOPES (and more) β mainly types, interfaces, or factory objects. Dependencies touch src.
Generated from folder role, exports, dependency roots, and inline comments β not hand-reviewed for every path.
π§ Inline summary
import { isEnvTruthy } from 'src/utils/envUtils.js' // Default to prod config, override with test/staging if enabled type OauthConfigType = 'prod' | 'staging' | 'local'
π€ Exports (heuristic)
fileSuffixForOauthConfigCLAUDE_AI_INFERENCE_SCOPECLAUDE_AI_PROFILE_SCOPEOAUTH_BETA_HEADERCONSOLE_OAUTH_SCOPESCLAUDE_AI_OAUTH_SCOPESALL_OAUTH_SCOPESMCP_CLIENT_METADATA_URLgetOauthConfig
π External import roots
Package roots from from "β¦" (relative paths omitted).
src
π₯οΈ Source preview
import { isEnvTruthy } from 'src/utils/envUtils.js'
// Default to prod config, override with test/staging if enabled
type OauthConfigType = 'prod' | 'staging' | 'local'
function getOauthConfigType(): OauthConfigType {
if (process.env.USER_TYPE === 'ant') {
if (isEnvTruthy(process.env.USE_LOCAL_OAUTH)) {
return 'local'
}
if (isEnvTruthy(process.env.USE_STAGING_OAUTH)) {
return 'staging'
}
}
return 'prod'
}
export function fileSuffixForOauthConfig(): string {
if (process.env.CLAUDE_CODE_CUSTOM_OAUTH_URL) {
return '-custom-oauth'
}
switch (getOauthConfigType()) {
case 'local':
return '-local-oauth'
case 'staging':
return '-staging-oauth'
case 'prod':
// No suffix for production config
return ''
}
}
export const CLAUDE_AI_INFERENCE_SCOPE = 'user:inference' as const
export const CLAUDE_AI_PROFILE_SCOPE = 'user:profile' as const
const CONSOLE_SCOPE = 'org:create_api_key' as const
export const OAUTH_BETA_HEADER = 'oauth-2025-04-20' as const
// Console OAuth scopes - for API key creation via Console
export const CONSOLE_OAUTH_SCOPES = [
CONSOLE_SCOPE,
CLAUDE_AI_PROFILE_SCOPE,
] as const
// Claude.ai OAuth scopes - for Claude.ai subscribers (Pro/Max/Team/Enterprise)
export const CLAUDE_AI_OAUTH_SCOPES = [
CLAUDE_AI_PROFILE_SCOPE,
CLAUDE_AI_INFERENCE_SCOPE,
'user:sessions:claude_code',
'user:mcp_servers',
'user:file_upload',
] as const
// All OAuth scopes - union of all scopes used in Claude CLI
// When logging in, request all scopes in order to handle both Console -> Claude.ai redirect
// Ensure that `OAuthConsentPage` in apps repo is kept in sync with this list.
export const ALL_OAUTH_SCOPES = Array.from(
new Set([...CONSOLE_OAUTH_SCOPES, ...CLAUDE_AI_OAUTH_SCOPES]),
)
type OauthConfig = {
BASE_API_URL: string
CONSOLE_AUTHORIZE_URL: string
CLAUDE_AI_AUTHORIZE_URL: string
/**
* The claude.ai web origin. Separate from CLAUDE_AI_AUTHORIZE_URL because
* that now routes through claude.com/cai/* for attribution β deriving
* .origin from it would give claude.com, breaking links to /code,
* /settings/connectors, and other claude.ai web pages.
*/
CLAUDE_AI_ORIGIN: string
TOKEN_URL: string
API_KEY_URL: string
ROLES_URL: string
CONSOLE_SUCCESS_URL: string
CLAUDEAI_SUCCESS_URL: string
MANUAL_REDIRECT_URL: string
CLIENT_ID: string
OAUTH_FILE_SUFFIX: string
MCP_PROXY_URL: string
MCP_PROXY_PATH: string
}
// Production OAuth configuration - Used in normal operation
const PROD_OAUTH_CONFIG = {
BASE_API_URL: 'https://api.anthropic.com',
CONSOLE_AUTHORIZE_URL: 'https://platform.claude.com/oauth/authorize',
// Bounces through claude.com/cai/* so CLI sign-ins connect to claude.com
// visits for attribution. 307s to claude.ai/oauth/authorize in two hops.
CLAUDE_AI_AUTHORIZE_URL: 'https://claude.com/cai/oauth/authorize',
CLAUDE_AI_ORIGIN: 'https://claude.ai',
TOKEN_URL: 'https://platform.claude.com/v1/oauth/token',
API_KEY_URL: 'https://api.anthropic.com/api/oauth/claude_cli/create_api_key',
ROLES_URL: 'https://api.anthropic.com/api/oauth/claude_cli/roles',
CONSOLE_SUCCESS_URL:
'https://platform.claude.com/buy_credits?returnUrl=/oauth/code/success%3Fapp%3Dclaude-code',
CLAUDEAI_SUCCESS_URL:
'https://platform.claude.com/oauth/code/success?app=claude-code',
MANUAL_REDIRECT_URL: 'https://platform.claude.com/oauth/code/callback',
CLIENT_ID: '9d1c250a-e61b-44d9-88ed-5944d1962f5e',
// No suffix for production config
OAUTH_FILE_SUFFIX: '',
MCP_PROXY_URL: 'https://mcp-proxy.anthropic.com',
MCP_PROXY_PATH: '/v1/mcp/{server_id}',
} as const
/**
* Client ID Metadata Document URL for MCP OAuth (CIMD / SEP-991).
* When an MCP auth server advertises client_id_metadata_document_supported: true,
* Claude Code uses this URL as its client_id instead of Dynamic Client Registration.
* The URL must point to a JSON document hosted by Anthropic.
* See: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00
*/
export const MCP_CLIENT_METADATA_URL =
'https://claude.ai/oauth/claude-code-client-metadata'
// Staging OAuth configuration - only included in ant builds with staging flag
// Uses literal check for dead code elimination
const STAGING_OAUTH_CONFIG =
process.env.USER_TYPE === 'ant'
? ({
BASE_API_URL: 'https://api-staging.anthropic.com',
CONSOLE_AUTHORIZE_URL:
'https://platform.staging.ant.dev/oauth/authorize',
CLAUDE_AI_AUTHORIZE_URL:
'https://claude-ai.staging.ant.dev/oauth/authorize',
CLAUDE_AI_ORIGIN: 'https://claude-ai.staging.ant.dev',
TOKEN_URL: 'https://platform.staging.ant.dev/v1/oauth/token',
API_KEY_URL:
'https://api-staging.anthropic.com/api/oauth/claude_cli/create_api_key',
ROLES_URL:
'https://api-staging.anthropic.com/api/oauth/claude_cli/roles',
CONSOLE_SUCCESS_URL:
'https://platform.staging.ant.dev/buy_credits?returnUrl=/oauth/code/success%3Fapp%3Dclaude-code',
CLAUDEAI_SUCCESS_URL:
'https://platform.staging.ant.dev/oauth/code/success?app=claude-code',
MANUAL_REDIRECT_URL:
'https://platform.staging.ant.dev/oauth/code/callback',
CLIENT_ID: '22422756-60c9-4084-8eb7-27705fd5cf9a',
OAUTH_FILE_SUFFIX: '-staging-oauth',
MCP_PROXY_URL: 'https://mcp-proxy-staging.anthropic.com',
MCP_PROXY_PATH: '/v1/mcp/{server_id}',
} as const)
: undefined
// Three local dev servers: :8000 api-proxy (`api dev start -g ccr`),
// :4000 claude-ai frontend, :3000 Console frontend. Env vars let
// scripts/claude-localhost override if your layout differs.
function getLocalOauthConfig(): OauthConfig {
const api =
process.env.CLAUDE_LOCAL_OAUTH_API_BASE?.replace(/\/$/, '') ??
'http://localhost:8000'
const apps =
process.env.CLAUDE_LOCAL_OAUTH_APPS_BASE?.replace(/\/$/, '') ??
'http://localhost:4000'
const consoleBase =
process.env.CLAUDE_LOCAL_OAUTH_CONSOLE_BASE?.replace(/\/$/, '') ??
'http://localhost:3000'
return {
BASE_API_URL: api,
CONSOLE_AUTHORIZE_URL: `${consoleBase}/oauth/authorize`,
CLAUDE_AI_AUTHORIZE_URL: `${apps}/oauth/authorize`,
CLAUDE_AI_ORIGIN: apps,
TOKEN_URL: `${api}/v1/oauth/token`,
API_KEY_URL: `${api}/api/oauth/claude_cli/create_api_key`,
ROLES_URL: `${api}/api/oauth/claude_cli/roles`,
CONSOLE_SUCCESS_URL: `${consoleBase}/buy_credits?returnUrl=/oauth/code/success%3Fapp%3Dclaude-code`,
CLAUDEAI_SUCCESS_URL: `${consoleBase}/oauth/code/success?app=claude-code`,
MANUAL_REDIRECT_URL: `${consoleBase}/oauth/code/callback`,
CLIENT_ID: '22422756-60c9-4084-8eb7-27705fd5cf9a',
OAUTH_FILE_SUFFIX: '-local-oauth',
MCP_PROXY_URL: 'http://localhost:8205',
MCP_PROXY_PATH: '/v1/toolbox/shttp/mcp/{server_id}',
}
}
// Allowed base URLs for CLAUDE_CODE_CUSTOM_OAUTH_URL override.
// Only FedStart/PubSec deployments are permitted to prevent OAuth tokens
// from being sent to arbitrary endpoints.
const ALLOWED_OAUTH_BASE_URLS = [
'https://beacon.claude-ai.staging.ant.dev',
'https://claude.fedstart.com',
'https://claude-staging.fedstart.com',
]
// Default to prod config, override with test/staging if enabled
export function getOauthConfig(): OauthConfig {
let config: OauthConfig = (() => {
switch (getOauthConfigType()) {
case 'local':
return getLocalOauthConfig()
case 'staging':
return STAGING_OAUTH_CONFIG ?? PROD_OAUTH_CONFIG
case 'prod':
return PROD_OAUTH_CONFIG
}
})()
// Allow overriding all OAuth URLs to point to an approved FedStart deployment.
// Only allowlisted base URLs are accepted to prevent credential leakage.
const oauthBaseUrl = process.env.CLAUDE_CODE_CUSTOM_OAUTH_URL
if (oauthBaseUrl) {
const base = oauthBaseUrl.replace(/\/$/, '')
if (!ALLOWED_OAUTH_BASE_URLS.includes(base)) {
throw new Error(
'CLAUDE_CODE_CUSTOM_OAUTH_URL is not an approved endpoint.',
)
}
config = {
...config,
BASE_API_URL: base,
CONSOLE_AUTHORIZE_URL: `${base}/oauth/authorize`,
CLAUDE_AI_AUTHORIZE_URL: `${base}/oauth/authorize`,
CLAUDE_AI_ORIGIN: base,
TOKEN_URL: `${base}/v1/oauth/token`,
API_KEY_URL: `${base}/api/oauth/claude_cli/create_api_key`,
ROLES_URL: `${base}/api/oauth/claude_cli/roles`,
CONSOLE_SUCCESS_URL: `${base}/oauth/code/success?app=claude-code`,
CLAUDEAI_SUCCESS_URL: `${base}/oauth/code/success?app=claude-code`,
MANUAL_REDIRECT_URL: `${base}/oauth/code/callback`,
OAUTH_FILE_SUFFIX: '-custom-oauth',
}
}
// Allow CLIENT_ID override via environment variable (e.g., for Xcode integration)
const clientIdOverride = process.env.CLAUDE_CODE_OAUTH_CLIENT_ID
if (clientIdOverride) {
config = {
...config,
CLIENT_ID: clientIdOverride,
}
}
return config
}