A Rust library for Kimi (Moonshot) OAuth Device Authorization.
Provides both synchronous (blocking) and asynchronous APIs for authenticating with Kimi's OAuth device flow endpoints.
- Sync & Async APIs - Choose blocking or async based on your needs
- OAuth Device Flow - CLI-friendly device authorization (RFC 8628 style)
- Kimi Device Headers - Sends required
X-Msh-*metadata headers - Auto Polling - Built-in handling for
authorization_pendingandslow_down - Token Refresh - Refresh access tokens using refresh token
- Browser Integration - Optional helper to auto-open verification URL
- Configurable - Override client ID, endpoints, and device metadata
- No Token Storage - You control where and how to persist tokens
[dependencies]
kimi-auth = "0.1"use kimi_auth::{OAuthClient, OAuthConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = OAuthClient::new(OAuthConfig::default())?;
// Calls Kimi device authorization endpoint
let flow = client.start_flow()?;
println!("Visit: {}", flow.verification_uri_complete);
println!("Enter code: {}", flow.user_code);
// After user authorizes in browser:
let tokens = client.poll_for_token(&flow)?;
println!("Got token, expires in: {:?}", tokens.expires_in());
// Later, refresh if needed
if tokens.is_expired() {
let new_tokens = client.refresh_token(&tokens.refresh_token)?;
println!("Refreshed, expires in: {:?}", new_tokens.expires_in());
}
Ok(())
}use kimi_auth::{AsyncOAuthClient, OAuthConfig};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = AsyncOAuthClient::new(OAuthConfig::default())?;
// Calls Kimi device authorization endpoint
let flow = client.start_flow().await?;
println!("Visit: {}", flow.verification_uri_complete);
println!("Enter code: {}", flow.user_code);
// After user authorizes in browser:
let tokens = client.poll_for_token(&flow).await?;
println!("Got token, expires in: {:?}", tokens.expires_in());
Ok(())
}| Feature | Description | Default |
|---|---|---|
blocking |
Synchronous/blocking API | Yes |
async |
Asynchronous API | No |
browser |
Auto-open browser for verification URL | Yes |
rustls-tls |
TLS via rustls for reqwest | Yes |
native-tls |
TLS via native-tls for reqwest | No |
full |
Enable all crate features (except native-tls) |
No |
[dependencies]
kimi-auth = { version = "0.1", default-features = false, features = ["async", "rustls-tls"] }use kimi_auth::{OAuthClient, OAuthConfig};
let config = OAuthConfig::builder()
.platform("my-cli")
.app_version("1.0.0")
.device_name("workstation")
.build();
let client = OAuthClient::new(config)?;Use kimi_cli_oauth_config() if you want X-Msh-* defaults aligned with Kimi CLI behavior and stable device identity across login/refresh calls.
use kimi_auth::{OAuthClient, kimi_cli_oauth_config};
let client = OAuthClient::new(kimi_cli_oauth_config())?;| Variable | Description |
|---|---|
KIMI_CLIENT_ID |
Override OAuth client ID |
KIMI_MSH_PLATFORM |
Override X-Msh-Platform |
KIMI_MSH_VERSION |
Override X-Msh-Version |
KIMI_MSH_DEVICE_NAME |
Override X-Msh-Device-Name |
KIMI_MSH_DEVICE_MODEL |
Override X-Msh-Device-Model |
KIMI_MSH_OS_VERSION |
Override X-Msh-Os-Version |
KIMI_MSH_DEVICE_ID |
Override X-Msh-Device-Id |
See the examples/ directory for complete examples:
01_basic_manual_sync.rs- Basic sync flow02_with_browser_sync.rs- Sync flow with browser auto-open03_basic_manual_async.rs- Basic async flow04_refresh_token_sync.rs- Refresh token flow (sync)05_custom_config_sync.rs- Custom configuration06_poll_custom_timeout_async.rs- Async flow with custom polling timeout
Run examples with:
cargo run --example 01_basic_manual_sync
cargo run --example 02_with_browser_sync
cargo run --example 03_basic_manual_async --features async
cargo run --example 06_poll_custom_timeout_async --features asyncuse kimi_auth::OAuthClient;
let client = OAuthClient::new(config)?;
let flow = client.start_flow()?;
let tokens = client.poll_for_token(&flow)?;
let refreshed = client.refresh_token(&tokens.refresh_token)?;use kimi_auth::AsyncOAuthClient;
let client = AsyncOAuthClient::new(config)?;
let flow = client.start_flow().await?;
let tokens = client.poll_for_token(&flow).await?;
let refreshed = client.refresh_token(&tokens.refresh_token).await?;use kimi_auth::open_browser;
open_browser(&flow.verification_uri_complete)?;- This crate does not persist tokens for you.
- Persist
TokenSetsecurely using your preferred storage (keyring, encrypted file, etc.). - If you want stable device identity across sessions, configure
device_idexplicitly.
MIT