Documentation
¶
Overview ¶
Package auth handles credential storage and OAuth flows for AI providers.
Credentials are stored in ~/.config/moa/auth.json with mode 0600. Supports both API keys and OAuth tokens (Claude Max).
Index ¶
- func DefaultStorePath() string
- func IsOAuthToken(key string) bool
- func OpenBrowser(url string)
- type Credential
- type MetaCredentials
- type MetaDeviceCode
- type OAuthCredentials
- func CompleteXAIDeviceFlow(ctx context.Context, client *http.Client, _ XAIEndpoints, ...) (*OAuthCredentials, error)
- func LoginAnthropic(openURL func(string), promptCode func() (string, error)) (*OAuthCredentials, error)
- func LoginOpenAI(openURL func(string), promptCode func() (string, error)) (*OAuthCredentials, error)
- func LoginXAI(ctx context.Context, openURL func(string), display func(*XAIDeviceCode)) (*OAuthCredentials, error)
- func RefreshAnthropicToken(refreshToken string) (*OAuthCredentials, error)
- func RefreshOpenAIToken(refreshToken string) (*OAuthCredentials, error)
- func RefreshXAIToken(refreshToken string) (*OAuthCredentials, error)
- type Store
- func (s *Store) CredentialKind(provider string) string
- func (s *Store) Get(provider string) (Credential, bool)
- func (s *Store) GetAPIKey(provider string) (key string, isOAuth bool, err error)
- func (s *Store) GetAccountID(provider string) string
- func (s *Store) PeekOAuthToken(provider string) (token string, isOAuth, valid bool)
- func (s *Store) RefreshOAuthIfCurrent(provider, rejected string) (string, error)
- func (s *Store) Remove(provider string) error
- func (s *Store) Set(provider string, cred Credential) error
- type XAIDeviceCode
- type XAIEndpoints
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DefaultStorePath ¶
func DefaultStorePath() string
DefaultStorePath returns the default path for the auth store, or "" when no config directory can be resolved.
func IsOAuthToken ¶
IsOAuthToken returns true if the given key looks like an OAuth token rather than a standard API key. Detects Anthropic OAuth (sk-ant-oat) and JWT tokens (three dot-separated segments, as used by OpenAI OAuth).
Types ¶
type Credential ¶
type Credential struct {
Type string `json:"type"` // "api_key" or "oauth"
Key string `json:"key,omitempty"` // API key (type=api_key), or a key minted from an OAuth session (Meta)
Access string `json:"access,omitempty"` // OAuth access token (type=oauth)
Refresh string `json:"refresh,omitempty"` // OAuth refresh token (type=oauth)
Expires int64 `json:"expires,omitempty"` // OAuth token expiry (unix ms) (type=oauth)
AccountID string `json:"account_id,omitempty"` // Provider-specific account ID (e.g., OpenAI chatgpt_account_id)
}
Credential represents a stored credential for a provider.
type MetaCredentials ¶ added in v0.37.0
type MetaCredentials struct {
OAuthCredentials
APIKey string
}
MetaCredentials is a completed Muse subscription login: the OAuth tokens plus the Model API key minted from them. The key — not the access token — is what /v1/responses accepts.
func LoginMeta ¶ added in v0.37.0
func LoginMeta(ctx context.Context, openURL func(string), display func(*MetaDeviceCode)) (*MetaCredentials, error)
LoginMeta runs the Muse device flow and mints a Model API key from the resulting access token.
func RefreshMetaToken ¶ added in v0.37.0
func RefreshMetaToken(refreshToken string) (*MetaCredentials, error)
RefreshMetaToken renews a Muse subscription login and re-mints its Model API key. The refresh grant is unverified — the launcher never refreshes — so a failure asks for a fresh login instead of guessing further.
type MetaDeviceCode ¶ added in v0.37.0
type MetaDeviceCode struct {
DeviceCode string
UserCode string
VerificationURI string
VerificationURIComplete string
ExpiresIn time.Duration
Interval time.Duration
}
MetaDeviceCode is the user-facing part of a device authorization request.
type OAuthCredentials ¶
type OAuthCredentials struct {
Access string `json:"access"`
Refresh string `json:"refresh"`
Expires int64 `json:"expires"` // Unix milliseconds
AccountID string `json:"account_id,omitempty"` // OpenAI chatgpt_account_id
// APIKey is a provider key derived from the OAuth session instead of the
// access token: Meta mints a Model API key, and api.meta.ai does not
// accept the access token itself.
APIKey string `json:"api_key,omitempty"`
}
OAuthCredentials holds the result of an OAuth login/refresh.
func CompleteXAIDeviceFlow ¶ added in v0.26.0
func CompleteXAIDeviceFlow(ctx context.Context, client *http.Client, _ XAIEndpoints, device *XAIDeviceCode) (*OAuthCredentials, error)
CompleteXAIDeviceFlow uses the endpoint and expiry captured at authorization; it never rediscovers metadata or restarts the device-code lifetime.
func LoginAnthropic ¶
func LoginAnthropic(openURL func(string), promptCode func() (string, error)) (*OAuthCredentials, error)
LoginAnthropic runs the Anthropic OAuth PKCE flow (device code style): 1. Generate PKCE verifier + challenge 2. Open browser to Anthropic authorize URL 3. User approves and sees a code on Anthropic's callback page 4. User pastes the code back into the CLI 5. Exchange code for tokens
promptCode is called to get the authorization code from the user. It receives the auth URL (for display) and should return the pasted code string.
func LoginOpenAI ¶
func LoginOpenAI(openURL func(string), promptCode func() (string, error)) (*OAuthCredentials, error)
LoginOpenAI runs the OpenAI PKCE OAuth flow with a local callback server. Returns credentials including the accountId extracted from the JWT.
openURL is called to open the browser. promptCode is the fallback if the local server doesn't receive the callback.
func LoginXAI ¶ added in v0.26.0
func LoginXAI(ctx context.Context, openURL func(string), display func(*XAIDeviceCode)) (*OAuthCredentials, error)
func RefreshAnthropicToken ¶
func RefreshAnthropicToken(refreshToken string) (*OAuthCredentials, error)
RefreshAnthropicToken refreshes an expired OAuth token.
func RefreshOpenAIToken ¶
func RefreshOpenAIToken(refreshToken string) (*OAuthCredentials, error)
RefreshOpenAIToken refreshes an expired OpenAI OAuth token.
func RefreshXAIToken ¶ added in v0.26.0
func RefreshXAIToken(refreshToken string) (*OAuthCredentials, error)
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store manages credentials on disk.
func (*Store) CredentialKind ¶ added in v0.26.0
CredentialKind reports the credential origin without inspecting token contents. Environment values are always API keys, including JWT-shaped xAI values, so transport selection cannot be confused by token syntax.
func (*Store) Get ¶
func (s *Store) Get(provider string) (Credential, bool)
Get retrieves a credential for a provider.
func (*Store) GetAPIKey ¶
GetAPIKey resolves the API key for a provider. Priority:
- Environment variable (ANTHROPIC_API_KEY, etc.)
- OAuth token from store (auto-refreshed if expired)
- API key from store
Returns the key and whether it's an OAuth token.
func (*Store) GetAccountID ¶
GetAccountID returns the stored account ID for a provider (e.g., OpenAI chatgpt_account_id).
func (*Store) PeekOAuthToken ¶
PeekOAuthToken returns the current OAuth access token for a provider WITHOUT triggering a refresh. It is for read-only, best-effort callers (e.g. the plan usage widget) that must never rotate the shared refresh token.
- isOAuth is true when an OAuth credential is in use for the provider.
- valid is true only when a non-expired access token is available.
When isOAuth is true but valid is false, the token has expired: the caller should treat usage as temporarily unavailable rather than refresh, and let a real API call renew the token on demand.
func (*Store) RefreshOAuthIfCurrent ¶ added in v0.26.0
RefreshOAuthIfCurrent reactively rotates an OAuth token that a consumer API rejected. If another request already rotated it, that newer token is reused. It deliberately never considers environment variables: those are API keys.
type XAIDeviceCode ¶ added in v0.26.0
type XAIDeviceCode struct {
DeviceCode string
UserCode string
VerificationURI string
VerificationURIComplete string
ExpiresIn time.Duration
Interval time.Duration
// contains filtered or unexported fields
}
XAIDeviceCode is the user-facing part of an RFC 8628 authorization request.
func StartXAIDeviceFlow ¶ added in v0.26.0
func StartXAIDeviceFlow(ctx context.Context, client *http.Client, endpoints XAIEndpoints) (*XAIDeviceCode, error)
type XAIEndpoints ¶ added in v0.26.0
type XAIEndpoints struct {
DiscoveryURL string
AllowedHosts []string
AllowedIssuers []string
AllowHTTP bool
Wait func(context.Context, time.Duration) error
Now func() time.Time
}
XAIEndpoints is test configuration for the xAI OIDC client. Production must leave it empty: that pins discovery, issuer, and endpoints to auth.x.ai. A non-default endpoint requires an explicit host allowlist. AllowHTTP and Wait are intended only for local tests.