2026-01-08 09:29:29 +01:00
---
2026-01-30 03:15:10 +01:00
summary: "OAuth in OpenClaw: token exchange, storage, and multi-account patterns"
2026-01-08 09:29:29 +01:00
read_when:
2026-01-30 03:15:10 +01:00
- You want to understand OpenClaw OAuth end-to-end
2026-01-08 09:29:29 +01:00
- You hit token invalidation / logout issues
2026-01-26 19:04:46 +00:00
- You want setup-token or OAuth auth flows
2026-01-08 09:29:29 +01:00
- You want multiple accounts or profile routing
2026-01-31 16:04:03 -05:00
title: "OAuth"
2026-01-08 09:29:29 +01:00
---
2026-01-31 21:13:13 +09:00
2026-01-08 09:29:29 +01:00
# OAuth
2026-03-03 00:02:25 +00:00
OpenClaw supports “subscription auth” via OAuth for providers that offer it (notably **OpenAI Codex (ChatGPT OAuth)** ). For Anthropic subscriptions, use the **setup-token** flow. Anthropic subscription use outside Claude Code has been restricted for some users in the past, so treat it as a user-choice risk and verify current Anthropic policy yourself. OpenAI Codex OAuth is explicitly supported for use in external tools like OpenClaw. This page explains:
For Anthropic in production, API key auth is the safer recommended path over subscription setup-token auth.
2026-01-08 09:29:29 +01:00
- how the OAuth **token exchange** works (PKCE)
- where tokens are **stored** (and why)
- how to handle **multiple accounts** (profiles + per-session overrides)
2026-01-30 03:15:10 +01:00
OpenClaw also supports **provider plugins** that ship their own OAuth or API‑ key
2026-01-16 00:39:29 +00:00
flows. Run them via:
```bash
2026-01-30 03:15:10 +01:00
openclaw models auth login --provider < id >
2026-01-16 00:39:29 +00:00
```
2026-01-08 09:29:29 +01:00
## The token sink (why it exists)
OAuth providers commonly mint a **new refresh token** during login/refresh flows. Some providers (or OAuth clients) can invalidate older refresh tokens when a new one is issued for the same user/app.
Practical symptom:
2026-01-31 21:13:13 +09:00
- you log in via OpenClaw _and_ via Claude Code / Codex CLI → one of them randomly gets “logged out” later
2026-01-08 09:29:29 +01:00
2026-01-30 03:15:10 +01:00
To reduce that, OpenClaw treats `auth-profiles.json` as a **token sink** :
2026-01-31 21:13:13 +09:00
2026-01-08 09:29:29 +01:00
- the runtime reads credentials from **one place**
- we can keep multiple profiles and route them deterministically
## Storage (where tokens live)
Secrets are stored **per-agent** :
2026-02-24 16:26:51 -06:00
- Auth profiles (OAuth + API keys + optional value-level refs): `~/.openclaw/agents/<agentId>/agent/auth-profiles.json`
- Legacy compatibility file: `~/.openclaw/agents/<agentId>/agent/auth.json`
(static `api_key` entries are scrubbed when discovered)
2026-01-08 09:29:29 +01:00
Legacy import-only file (still supported, but not the main store):
2026-01-31 21:13:13 +09:00
2026-01-30 03:15:10 +01:00
- `~/.openclaw/credentials/oauth.json` (imported into `auth-profiles.json` on first use)
2026-01-08 09:29:29 +01:00
2026-01-30 03:15:10 +01:00
All of the above also respect `$OPENCLAW_STATE_DIR` (state dir override). Full reference: [/gateway/configuration ](/gateway/configuration#auth-storage-oauth--api-keys )
2026-01-08 09:29:29 +01:00
2026-02-24 16:26:51 -06:00
For static secret refs and runtime snapshot activation behavior, see [Secrets Management ](/gateway/secrets ).
2026-01-26 19:04:46 +00:00
## Anthropic setup-token (subscription auth)
2026-01-08 09:29:29 +01:00
2026-03-03 00:02:25 +00:00
< Warning >
Anthropic setup-token support is technical compatibility, not a policy guarantee.
Anthropic has blocked some subscription usage outside Claude Code in the past.
Decide for yourself whether to use subscription auth, and verify Anthropic's current terms.
< / Warning >
2026-01-30 03:15:10 +01:00
Run `claude setup-token` on any machine, then paste it into OpenClaw:
2026-01-08 09:29:29 +01:00
2026-01-26 19:04:46 +00:00
```bash
2026-01-30 03:15:10 +01:00
openclaw models auth setup-token --provider anthropic
2026-01-26 19:04:46 +00:00
```
2026-01-08 09:29:29 +01:00
2026-01-26 19:04:46 +00:00
If you generated the token elsewhere, paste it manually:
2026-01-08 09:29:29 +01:00
```bash
2026-01-30 03:15:10 +01:00
openclaw models auth paste-token --provider anthropic
2026-01-08 09:29:29 +01:00
```
2026-01-26 19:04:46 +00:00
Verify:
2026-01-08 09:29:29 +01:00
```bash
2026-01-30 03:15:10 +01:00
openclaw models status
2026-01-08 09:29:29 +01:00
```
## OAuth exchange (how login works)
2026-01-30 03:15:10 +01:00
OpenClaw’ s interactive login flows are implemented in `@mariozechner/pi-ai` and wired into the wizards/commands.
2026-01-08 09:29:29 +01:00
2026-03-03 00:02:25 +00:00
### Anthropic setup-token
2026-01-08 09:29:29 +01:00
2026-01-26 19:04:46 +00:00
Flow shape:
2026-01-08 09:29:29 +01:00
2026-01-31 21:13:13 +09:00
1. run `claude setup-token`
2. paste the token into OpenClaw
3. store as a token auth profile (no refresh)
2026-01-08 09:29:29 +01:00
2026-01-30 03:15:10 +01:00
The wizard path is `openclaw onboard` → auth choice `setup-token` (Anthropic).
2026-01-08 09:29:29 +01:00
### OpenAI Codex (ChatGPT OAuth)
2026-03-03 00:02:25 +00:00
OpenAI Codex OAuth is explicitly supported for use outside the Codex CLI, including OpenClaw workflows.
2026-01-08 09:29:29 +01:00
Flow shape (PKCE):
2026-01-31 21:13:13 +09:00
1. generate PKCE verifier/challenge + random `state`
2. open `https://auth.openai.com/oauth/authorize?...`
3. try to capture callback on `http://127.0.0.1:1455/auth/callback`
4. if callback can’ t bind (or you’ re remote/headless), paste the redirect URL/code
5. exchange at `https://auth.openai.com/oauth/token`
6. extract `accountId` from the access token and store `{ access, refresh, expires, accountId }`
2026-01-08 09:29:29 +01:00
2026-01-30 03:15:10 +01:00
Wizard path is `openclaw onboard` → auth choice `openai-codex` .
2026-01-08 09:29:29 +01:00
## Refresh + expiry
Profiles store an `expires` timestamp.
At runtime:
2026-01-31 21:13:13 +09:00
2026-01-08 09:29:29 +01:00
- if `expires` is in the future → use the stored access token
- if expired → refresh (under a file lock) and overwrite the stored credentials
2026-01-10 11:42:12 +00:00
The refresh flow is automatic; you generally don't need to manage tokens manually.
2026-01-08 09:29:29 +01:00
## Multiple accounts (profiles) + routing
Two patterns:
### 1) Preferred: separate agents
If you want “personal” and “work” to never interact, use isolated agents (separate sessions + credentials + workspace):
```bash
2026-01-30 03:15:10 +01:00
openclaw agents add work
openclaw agents add personal
2026-01-08 09:29:29 +01:00
```
Then configure auth per-agent (wizard) and route chats to the right agent.
### 2) Advanced: multiple profiles in one agent
`auth-profiles.json` supports multiple profile IDs for the same provider.
Pick which profile is used:
2026-01-31 21:13:13 +09:00
2026-01-08 09:29:29 +01:00
- globally via config ordering (`auth.order` )
- per-session via `/model ...@<profileId>`
Example (session override):
2026-01-31 21:13:13 +09:00
2026-01-08 09:29:29 +01:00
- `/model Opus@anthropic:work`
How to see what profile IDs exist:
2026-01-31 21:13:13 +09:00
2026-01-30 03:15:10 +01:00
- `openclaw channels list --json` (shows `auth[]` )
2026-01-08 09:29:29 +01:00
Related docs:
2026-01-31 21:13:13 +09:00
2026-01-08 09:29:29 +01:00
- [/concepts/model-failover ](/concepts/model-failover ) (rotation + cooldown rules)
- [/tools/slash-commands ](/tools/slash-commands ) (command surface)