Repository navigation
feat(auth): support client credentials grant - #147
Merged
Merged
Conversation
shadowhand
commented
Oct 9, 2026
shadowhand
left a comment
Contributor
Author
There was a problem hiding this comment.
This is an automated review by Rory.
Looks good, no issues found. The untagged enum order is correct and has a test. The secret stays out of status, show, and doctor output. The token goes to the AuthKit /oauth2/token endpoint for the profile's saved stage, and the new paths have tests.
There was a problem hiding this comment.
🟡 Changes recommended
Logout cannot recover from malformed auth caches, and related documentation remains incomplete or inaccurate.
4 open findings
What changed in this PR
Adds OAuth client-credentials authentication for non-interactive workflows.
Changes:
- Stores and exchanges client credentials with token caching.
- Adds CLI configuration, status, logout, and doctor support.
- Updates user and contributor documentation.
| File | Description |
|---|---|
src/prompt.rs |
Generalizes secure secret prompting. |
src/commands/config/profile.rs |
Configures and reports client credentials. |
src/commands/config/doctor.rs |
Diagnoses client-credential authentication. |
src/commands/auth.rs |
Exchanges, caches, reports, and clears tokens. |
src/cli.rs |
Adds client credential flags. |
src/auth_cache.rs |
Adds the client-credentials cache variant. |
README.md |
Documents the new workflow. |
docs/config.md |
Documents the cache format. |
CONTRIBUTING.md |
Updates the architecture overview. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Closes CL-9
Summary
client_id+client_secret, whichrwexchanges for an access token via the OAuthclient_credentialsgrant at the existing per-stage WorkOStoken_url.auth/{profile}.json(mode 0600) as a newAuthCache::ClientCredentialsvariant, declared beforeBearerbecause the enum is untagged. The exchanged token is cached in the same file and re-exchanged within 60s of expiry.rw config profile auth <name> --client-id … --client-secret …stores them (secret prompted if omitted; conflicts with--username/--password).rw auth status,rw config profile showandrw config doctorreport the new type without exposing the secret. Doctor exchanges against the profile's saved stage, not the-goverride.docs/config.md,README.md,CONTRIBUTING.md.Out of scope: environment-variable credentials (can be layered on later).
Test plan
cargo test(349 lib, 17 bin, 14 integration)cargo clippy --all-targets --all-features -- -D warningscargo fmt --checkrw config profile auth <p> --client-id … --client-secret …thenrw config doctoragainst a real WorkOS M2M app (whether the RoundingWell API accepts machine tokens, and whether/clinicians/meis meaningful for them, is unverified)Deferred minors
Tracked in CL-9: concurrent exchange can overwrite a credential rotation;
auth statushas noexpires_at;profile auth --jsonomits the auth type; whitespace-only values accepted; README doesn't mention logout/login replacing the secret; no retry on 401 for a revoked cached token.