Skip to main content
Version: MVP

Authentication and credentials

7 min readFor operatorsUpdated 2026-05-22

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:

  1. Claude CLI marker profile from craik auth login anthropic
  2. CLAUDE_CODE_OAUTH_TOKEN environment variable from claude setup-token
  3. ANTHROPIC_TOKEN environment variable for manual OAuth token overrides
  4. ANTHROPIC_API_KEY environment 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

Kind
When to use
Notes
keyring-ref
default interactive login
Created by craik auth login <provider>. The profile stores an opaque reference and backend metadata; credential material resolves through the local credential backend at request time.
cli-bridge
vendor subprocess
Vendor tools that mint a token through a subprocess. Supports stdout_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-ref
external secret manager
Built-in managers treat the ref as an env var name or local file path. Custom managers can implement the same resolver protocol for Vault, AWS Secrets Manager, cloud KMS brokers, or internal services.
stigmem-ref
team-shared
Resolve credential material from a Stigmem fact (typically relation craik:credential:value). Metadata includes node URL · entity · optional API key · scope · relation · timeout. Supports Stigmem provenance and revocation semantics.
marker
no-secret providers
For provider paths that intentionally need no secret (e.g., local OpenAI-compatible server). The provider receipt records a <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.

Platform
Source
Notes
GitHub Actions
Actions OIDC
Reads ACTIONS_ID_TOKEN_REQUEST_URL and ACTIONS_ID_TOKEN_REQUEST_TOKEN from the runner.
Kubernetes
projected token
Reads a projected service-account token from /var/run/secrets/tokens/craik by default.
Generic file / env-var
other CI
Supports any CI system that exposes a current OIDC token directly.

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

Symptom
Cause
Fix
Missing operator session
policy
A policy with required_operator=true fails before any provider call. Run craik login, then retry.
Expired OAuth token
credential
Local-CLI OAuth sources refresh when possible. If refresh cannot complete, the profile is reported as rejected or expired, and long-running case files surface token-expiry risk before the run starts.
Credential approval required
first-use gate
Run craik auth approve <profile_id> --run=<run_id> to unblock the run.

What's next