Authentication and credentials
What you'll do
Set up operator identity, register provider credential profiles, opt into approval-gated first-use, and bind credentials to policy. Every provider receipt names both the human who authorized the work and the credential that carried it.
Two identity axes.
Operator identity = the human or automation driving a run. Credential identity = the provider account behind model calls. Receipts record both — audit answers "who authorized this" and "which credential carried it out" without inspecting secret material.
Operator login
Use OIDC login when a policy requires an authenticated operator.
export CRAIK_OIDC_ISSUER=https://idp.example.com
export CRAIK_OIDC_CLIENT_ID=craik-cli
craik login
craik whoami
craik login starts the CLI device-code flow, prints the verification
URL and user code, validates the returned ID token against the issuer
JWKS, and stores the session at
<CRAIK_HOME>/operator-session.json with owner-only permissions. The
lower-level OIDC authenticator also supports loopback + PKCE for IdPs
and entrypoints that are configured to use a browser redirect.
End the local session with:
craik logout
Logout removes the session file and attempts refresh-token revocation when the issuer exposes a revocation endpoint.
Credential profiles
Profiles live in <CRAIK_HOME>/auth-profiles.json and use
<provider_family>:<name> IDs such as anthropic:work or
chat_completions:local. Profile metadata is masked in CLI output.
Guided setup
Use guided setup for the common provider families:
craik auth setup openai
craik auth setup anthropic
craik auth setup gemini
craik auth setup local --base-url http://localhost:11434/v1
The setup command writes a typed auth profile and, by default, a
single-profile credential pool. It prints redacted validation output
including credential health and missing-secret guidance. Use
--dry-run to validate the shape without writing state.
craik auth setup openai --dry-run
craik auth setup openai --secret-ref OPENAI_API_KEY --dry-run
Loopback HTTP base URLs are rejected unless the selected provider is
local or --allow-local-base-url is passed explicitly.
Provider login
Use craik auth login for the default provider setup flow. Craik chooses
the strongest supported flow per provider: OpenAI uses browser PKCE OAuth
when no OPENAI_API_KEY is set, local-compatible providers use API-key
capture, Anthropic delegates to the local Claude CLI, and Gemini
uses Google-managed ADC or service-account OAuth.
craik auth login openai
craik auth login anthropic
craik auth login gemini --project-id my-gcp-project
craik auth login local --base-url http://localhost:11434/v1
OpenAI opens a browser OAuth flow by default. Local-compatible providers, and
OpenAI when --no-browser, --mode=api-key, --dry-run, or an explicit
--env-var/--secret-ref is supplied, use API-key capture. In API-key mode
Craik opens the provider setup page when a browser is available, prompts for
the key with hidden terminal input, validates the shape, stores the credential
in the local credential backend, and writes a redacted keyring-ref profile.
Use --mode=api-key to force API-key capture where a provider otherwise uses
OAuth-backed or subscription-backed credentials:
craik auth login gemini --mode=api-key
For provider-specific OAuth endpoints, headers, setup commands, and current support status, see OAuth provider reference.
Use --json for automation-friendly redacted output. API-key capture can
preview the resulting profile without writing state:
craik auth login openai --json
craik auth login openai --dry-run --json
craik auth status shows the profile id, provider family, credential
kind, credential backend, last validated timestamp, and current
redacted health status. craik auth logout <provider> removes both the
profile and cached credential reference.
craik auth status
craik auth logout openai
Provider login configures provider credentials. Operator identity remains
available through craik login and craik whoami.
OpenAI login status
OpenAI defaults to browser PKCE OAuth when OPENAI_API_KEY is not set:
craik auth login openai
The OAuth path stores access and refresh tokens in the OS keyring and routes subsequent Craik usage through the operator's OpenAI consumer or workspace subscription quota. The pre-flight notice explains that the OpenAI consent screen identifies the requesting application as "Codex" because Craik uses OpenAI's public Codex OAuth client.
Set OPENAI_API_KEY, pass --no-browser, or run
craik auth login openai --mode=api-key to use Platform API key billing
instead.
Anthropic Claude CLI delegation
Anthropic credential sources resolve in this order:
- Claude CLI marker profile from
craik auth login anthropic CLAUDE_CODE_OAUTH_TOKENenvironment variable fromclaude setup-tokenANTHROPIC_TOKENenvironment variable for manual OAuth token overridesANTHROPIC_API_KEYenvironment variable
The first source that resolves wins. craik doctor and craik auth status
report which Anthropic source is active without printing credential material.
Anthropic defaults to claude-cli mode. When no environment credential is set,
Craik delegates live prompts to Anthropic's local Claude CLI:
craik auth login anthropic
Craik stores a marker profile and calls claude -p for Anthropic prompts
instead of replaying Claude OAuth tokens through Craik's HTTP transport. Run
claude first if Claude CLI is not already authenticated.
Use craik auth login anthropic --mode=api-key --no-browser to skip browser
token export and paste a traditional Console API key directly. --mode=oauth
is not used for this flow because Anthropic does not provide a supported Craik
browser OAuth flow.
Gemini and Vertex OAuth
Gemini defaults to Google-managed OAuth through google-auth.
For Application Default Credentials:
gcloud auth application-default login
craik auth login gemini --project-id my-gcp-project
For service accounts:
craik auth login gemini \
--project-id my-gcp-project \
--service-account /path/to/service-account.json
Craik stores the Gemini auth profile metadata, including project id and credential source. Google-managed credential material remains in ADC or the service-account file; Craik does not store Google refresh tokens.
OAuth credential material stays out of profile metadata.
Provider OAuth profiles store handles and setup metadata, not raw tokens.
OpenAI's pending OAuth path uses separate access-token and refresh-token
handles. Anthropic Claude CLI login stores only a marker profile and delegates
execution to claude -p. Gemini relies on Google-managed ADC or
service-account credentials.
Credential storage posture
Inspect the credential backend without printing secret material:
craik auth storage status
craik auth migrate-secrets --dry-run
On platforms where a native keychain is not available, Craik reports the file-backed fallback explicitly and keeps outputs redacted.
Explicit env-var or secret-ref mode
CI and unattended deployments can keep using explicit references instead of interactive capture:
craik auth login openai --env-var OPENAI_API_KEY
craik auth login anthropic --secret-ref ANTHROPIC_API_KEY
Existing v0.10.0-style env-var profiles can be migrated into cached credential storage without modifying the source environment variables:
craik auth migrate-from-env --dry-run
craik auth migrate-from-env --apply --yes
The migration is idempotent. Profiles already converted to
keyring-ref are skipped on later runs.
Env-var API key
export ANTHROPIC_API_KEY=...
craik auth add anthropic:work --kind=api-key --env-var=ANTHROPIC_API_KEY
craik auth test anthropic:work
Anthropic API-key profiles send x-api-key. Anthropic claude-cli profiles
call the local claude binary and strip Anthropic bearer-token environment
variables from the subprocess so the CLI uses its own authenticated session.
OpenAI and OpenAI-compatible Chat Completions profiles send
Authorization: Bearer.
Subscription tokens route differently.
Claude CLI delegation preserves Anthropic's first-party CLI auth and billing semantics. Direct API-key provider calls remain separate and are billed through Anthropic Console.
Other credential kinds
keyring-refcraik auth login <provider>. The profile stores an opaque reference and backend metadata; credential material resolves through the local credential backend at request time.cli-bridgestdout_json and stdout_line extractors. Today created by writing profile metadata into auth-profiles.json; the CLI does not yet expose dedicated bridge flags.secret-refstigmem-refcraik:credential:value). Metadata includes node URL · entity · optional API key · scope · relation · timeout. Supports Stigmem provenance and revocation semantics.marker<provider_family>:no-credential marker instead of a secret-bearing profile.Credential pool
Use a credential pool when a provider has multiple usable accounts and
the run should rotate or fail over between them. Pools are stored in
<CRAIK_HOME>/credential_pool.json.
round_robin
Even distribution.
failover
Primary first; fall over on failure.
weighted
Weighted selection by configured priority.
Per-profile health
Tracked across calls.
craik auth setup writes the default single-profile pool for guided
provider setup. More advanced pool strategies remain file-backed.
Approval flow
First live use of a profile is approval-gated.
When a run pauses with a credential approval request, approve the profile for that run.
craik auth approve anthropic:work --run=run_123
The approval is recorded as a receipt. Operator-to-profile authorization grants are also receipted:
craik auth grant anthropic:work --to-group=prod-deploy
craik auth grant anthropic:work --to-subject=operator-subject-123
Workload identity
Workload identity lets CI or cloud platforms mint short-lived credentials without storing long-lived provider secrets.
ACTIONS_ID_TOKEN_REQUEST_URL and ACTIONS_ID_TOKEN_REQUEST_TOKEN from the runner./var/run/secrets/tokens/craik by default.OIDC token exchange
The RFC 8693 token-exchange manager combines workload identity with an external broker. Craik sends a platform-issued OIDC token to the exchange endpoint and caches the returned short-lived credential until expiry. A common deployment is GitHub Actions OIDC exchanged for a provider credential that is never committed, printed, or stored as a long-lived secret in the repo.
Policy-bound auth
Policy envelopes can constrain both operators and credentials. This
example requires a logged-in operator from the corporate issuer,
restricts access to the prod-deploy group, and allows only
secret-manager-backed credentials.
{
"required_operator": true,
"required_operator_issuer": "https://idp.example.com",
"allowed_operator_groups": ["prod-deploy"],
"allowed_credential_kinds": ["secret-ref"],
"allowed_credential_profiles": ["anthropic:prod-*"]
}
Denied runs produce denial receipts that name the failing policy condition without exposing credential material.
Receipts and audit
Provider receipts include both identity dimensions:
auth_profile_id
auth_kind
auth_identity_hash
operator_subject
operator_issuer
operator_email
operator_groups
The identity hash is stable across runs but non-reversible. It supports queries like "every action taken by this operator" and "every action carried by this credential identity" without storing the raw credential or account identifier in the receipt.
Health check
craik auth status
Stored profile state.
craik doctor
Read-only health checks · env-var presence · local credential file readability · OAuth token expiry when the source can inspect it.
Common failures
required_operator=true fails before any provider call. Run craik login, then retry.craik auth approve <profile_id> --run=<run_id> to unblock the run.