import chalk from 'chalk'
import { exec } from 'child_process'import { execa } from 'execa'import { mkdir, stat } from 'fs/promises'import memoize from 'lodash-es/memoize.js'
import { join } from 'path'import { CLAUDE_AI_PROFILE_SCOPE } from 'src/constants/oauth.js'import {type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
logEvent,
} from 'src/services/analytics/index.js'
import { getModelStrings } from 'src/utils/model/modelStrings.js'import { getAPIProvider } from 'src/utils/model/providers.js'import {getIsNonInteractiveSession,
preferThirdPartyAuthentication,
} from '../bootstrap/state.js'
import {getMockSubscriptionType,
shouldUseMockSubscription,
} from '../services/mockRateLimits.js'
import {isOAuthTokenExpired,
refreshOAuthToken,
shouldUseClaudeAIAuth,
} from '../services/oauth/client.js'
import { getOauthProfileFromOauthToken } from '../services/oauth/getOauthProfile.js'import type { OAuthTokens, SubscriptionType } from '../services/oauth/types.js'import {getApiKeyFromFileDescriptor,
getOAuthTokenFromFileDescriptor,
} from './authFileDescriptor.js'
import {maybeRemoveApiKeyFromMacOSKeychainThrows,
normalizeApiKeyForConfig,
} from './authPortable.js'
import {checkStsCallerIdentity,
clearAwsIniCache,
isValidAwsStsOutput,
} from './aws.js'
import { AwsAuthStatusManager } from './awsAuthStatusManager.js'import { clearBetasCaches } from './betas.js'import {type AccountInfo,
checkHasTrustDialogAccepted,
getGlobalConfig,
saveGlobalConfig,
} from './config.js'
import { logAntError, logForDebugging } from './debug.js'import {getClaudeConfigHomeDir,
isBareMode,
isEnvTruthy,
isRunningOnHomespace,
} from './envUtils.js'
import { errorMessage } from './errors.js'import { execSyncWithDefaults_DEPRECATED } from './execFileNoThrow.js'import * as lockfile from './lockfile.js'
import { logError } from './log.js'import { memoizeWithTTLAsync } from './memoize.js'import { getSecureStorage } from './secureStorage/index.js'import {clearLegacyApiKeyPrefetch,
getLegacyApiKeyPrefetchResult,
} from './secureStorage/keychainPrefetch.js'
import {clearKeychainCache,
getMacOsKeychainStorageServiceName,
getUsername,
src/utils/auth.ts unifies authentication across three providers: Claude.ai OAuth, AWS Bedrock, and Google Cloud. Each has different token formats and refresh semantics, but they all expose the same interface to the rest of the app.
Tokens are stored in the OS keychain, not files. On macOS this is the Keychain; on Windows it's the credential store. This is more secure than `.env` files because keychain access requires explicit user authorization.
The refresh is proactive: a timer is set when a token is stored, firing 5 minutes before expiry. This means tokens are always fresh when a query starts — no "token expired" errors mid-conversation.
Keychain reads are prefetched at startup in parallel with other initialization. By the time the user types their first message, the auth token is already in memory — no keychain latency on the first API call.
Ask anything about OAuth & Authentication
Powered by Groq · Enter to send, Shift+Enter for newline