Authentication
How OpenKakao authenticates, how recovery policy works, and where unattended assumptions stop.
Authentication
OpenKakao derives authentication material from the running KakaoTalk macOS app and stores reusable credentials locally only when you ask it to.
Token classes
| Credential path | Source | Best for |
|---|---|---|
| saved credentials | ~/.config/openkakao/credentials.json | normal CLI startup |
| Cache.db extraction | recent KakaoTalk macOS request state | fallback when saved state is stale |
login.json relogin | reconstructed desktop login flow | restoring LOCO-facing commands |
refresh_token renewal | renewal endpoints + cached refresh token | supervised token refresh attempts |
auth.password_cmd | external secret command such as Doppler | unattended relogin without storing a plaintext password locally |
Transport boundary
- REST: profile, friends, settings, recently opened chats, cached messages
- LOCO: full chat list, full message history, send, watch, media flows
If you care about stable automation, use REST for cheap health checks and LOCO for real chat work. The fuller boundary is documented in REST vs LOCO.
Initial login
openkakao-rs login --saveThat command extracts the local inputs it needs, performs login, and writes credentials to:
~/.config/openkakao/credentials.jsonThe file is created with 0600 permissions.
Health checks
openkakao-rs auth
openkakao-rs doctor
openkakao-rs auth-statusUse auth for a fast REST-side check. Use doctor --loco when you need to know whether the stricter LOCO path is healthy too.
Use auth-status when you want the persisted recovery and cooldown state directly.
Recovery policy
openkakao-rs relogin --fresh-xvc
openkakao-rs renewThe recovery ladder is now policy-driven:
- reuse saved credentials
- try
reloginorrenewfirst depending on config - try the remaining recovery path if enabled
- fall back to fresh Cache.db extraction
Default behavior remains conservative:
auth.prefer_relogin = trueauth.auto_renew = true
That means the default credential loading order is:
- Saved credentials (
~/.config/openkakao/credentials.json) -- fastest path, no network call. The CLI checks this first on every invocation. login.jsonrelogin -- reconstructs the desktop login flow with X-VC header to get a fresh access_token (~65 chars). Works for both LOCO and REST.refresh_tokenrenewal -- uses the cached refresh_token to request a new access_token from renewal endpoints. Lighter than full relogin but depends on the refresh_token still being valid.- Fresh Cache.db extraction -- extracts the bearer token from the KakaoTalk macOS app's HTTP cache. This token (~138 chars) only works for REST, not LOCO. This is the last resort.
If you disable auto_renew, the refresh_token renewal step is skipped entirely. If you set prefer_relogin = false, the CLI attempts refresh_token renewal before login.json relogin.
If you set auth.password_cmd, relogin can source the password from an external command such as Doppler instead of relying only on cached request state.
Do not build unattended jobs that assume recovery will always succeed after upstream client or server changes.
The recovery context now persists in:
~/.config/openkakao/state.jsonThat lets watch, LOCO commands, and REST commands share cooldown history across process restarts.
Unattended mode
Commands that can create side effects without a human in the loop require an explicit global opt-in:
send -ysend-file -ysend-photo -ywatch --read-receiptwatch --hook-cmdwatch --webhook-url
Example:
openkakao-rs --unattended --allow-watch-side-effects watch --hook-cmd 'jq . > /tmp/event.json'The point is simple: if the CLI is going to act without waiting for you, you should have to say that plainly.
For persistent setups, move those permissions and auth policy into Configuration.
Failure patterns
| Code | Meaning | Typical response |
|---|---|---|
-950 | token expired or LOCO login rejected | run relogin, then verify whether renewal should still be enabled |
-300 | device or request mismatch | inspect identifiers, local app state, and login inputs |
-203 | missing required parameter (incomplete request body) | re-run login --save and verify extracted fields |
-400 | missing parameters | re-run login and validate extracted inputs |