0xPlaygrounds / 0xPlaygrounds/rig
feat(auth): support application-provided OAuth token storage
- Dominant language
- Rust
- Stars
- 8.6k
- Forks
- 959
- Avg merge
- 4h 32m
- Merged PRs (30d)
- 117
Description
- [x] I have looked for existing issues (including closed) about this
## Feature Request
Allow applications to supply the token storage used by the built-in ChatGPT and Copilot OAuth clients, while keeping Rig responsible for login, token refresh, and authenticated requests.
In Rig 0.42, these clients expose token-file paths through their builders. The shared [cache helpers on main](https://github.com/0xPlaygrounds/rig/blob/main/crates/rig-core/src/providers/internal/device_auth.rs) also read and write JSON files directly. I could not find a public interface for replacing that persistence with application-owned storage.
### Motivation
I maintain [Toad](https://github.com/1Broseidon/toad), a Rust/Tauri application using Rig for its native agents. We want provider credentials and MCP credentials to use the same OS-backed vault: macOS Keychain, Windows Credential Manager, and Linux Secret Service.
Ordinary API keys can already be loaded by the application and passed to Rig in memory. Built-in OAuth is different: Rig also persists tokens during login and refresh, so choosing a different file path does not let the application enforce its storage policy.
Other desktop applications, services with managed secret storage, and tests using an in-memory store could use the same extension point.
### Proposal
Add a caller-supplied OAuth token-store interface for ChatGPT and Copilot. The exact API shape is open for discussion; the intended behavior is:
- Route token reads, writes, and invalidation through the selected store, including Copilot's bootstrap credentials and derived token cache.
- Keep the existing file-backed behavior as the default.
- Keep login and refresh logic in Rig. An application selects persistence without implementing OAuth or replacing the inference client.
- Distinguish a missing record from an unavailable or failed store. A configured custom store must not silently fall back to writing token files.
- Define how the store participates in refresh coordination so concurrent clients do not overwrite rotated credentials.
The interface should follow Rig's error and WASM conventions. OS-specific implementations and dependencies can stay in the consuming application; this proposal does not require Rig to depend on a keychain library.
Tests could extend the existing ChatGPT/Copilot OAuth coverage with an in-memory/failing store, proving that login and refresh use it, failures propagate, and no default token files are created.
Related work: #2050 provides OAuth regression coverage, #2396 routes auth through the generic HTTP client, and #2088 includes useful discussion of refresh locking and preserving credentials after failed writes. #1905 also touches shared auth code, but its token persistence remains file-based.
I'm happy to contribute a focused PR once we agree on the storage boundary.
### Alternatives
- Restrict permissions on the existing token files. That limits file access but does not integrate with the application's OS credential store.
- Copy tokens between the vault and temporary files around Rig calls. This still creates plaintext copies and complicates refresh, cancellation, and crash recovery.
- Own OAuth outside Rig and inject access tokens. That duplicates login/refresh behavior we would prefer to keep in Rig.
- Add a specific keychain backend directly to Rig. A storage interface would let callers choose their backend without imposing native dependencies on everyone.
Contributor guide
Research direction
The issue mentions token storage in crates/rig-core/src/providers/internal/device_auth.rs and references existing OAuth clients for ChatGPT and Copilot. Start by examining the current file-based token storage implementation there. Review related issues #2050, #2396, #2088, and #1905 for context on auth flow and refresh coordination. The goal is to design a storage interface that applications can implement, ensuring it works with login/refresh logic and does not silently fall back to files.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- authentication, backend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 45/100