OAuth Authentication Flow in Kimi CLI: Technical Implementation and Platform Integration

Kimi CLI implements a standard OAuth 2.0 Authorization Code flow that opens a browser for user consent, receives the authorization code via a temporary local server, exchanges it for an access token at https://auth.kimi.ai/token, and persists credentials in the local configuration store.

The Kimi CLI (hosted in the MoonshotAI/kimi-cli repository) authenticates users against the Kimi platform through a secure, multi-layered OAuth authentication flow. This implementation leverages Python's async generators and temporary HTTP servers to bridge the browser-based authorization process with the command-line interface, ensuring tokens are securely stored and validated for subsequent API requests.

Three-Layer OAuth Architecture

The OAuth authentication flow in Kimi CLI is divided into three distinct architectural layers that handle user interaction, protocol negotiation, and request validation.

CLI UI Layer (src/kimi_cli/ui/shell/oauth.py): Exposes the login and logout commands to users. The login() function triggers the authentication sequence and manages shell reloads after successful token acquisition.

OAuth Helper Layer (src/kimi_cli/auth/oauth.py): Contains the core login_kimi_code() and logout_kimi_code() async generators. These functions manage the temporary local HTTP server, browser redirection, token exchange, and configuration persistence.

Web-API Middleware Layer (src/kimi_cli/web/auth.py): Implements AuthMiddleware to validate bearer tokens on every incoming request. The middleware extracts tokens from Authorization headers and enforces origin rules using verify_token().

Step-by-Step OAuth Authorization Code Flow

When a user executes kimi login, the CLI orchestrates the following sequence:

  1. Platform Selection: The shell command selects the Kimi platform using the constant KIMI_CODE_PLATFORM_ID defined in src/kimi_cli/auth/platforms.py.

  2. Authorization Request: The login_kimi_code() helper constructs a URL pointing to https://auth.kimi.ai/authorize and launches the system browser via webbrowser.open().

  3. Local Callback Server: A temporary uvicorn HTTP server starts on a random local port (localhost:<random-port>) to receive the OAuth callback.

  4. User Authorization: After the user approves the application in the browser, the Kimi auth service redirects to http://localhost:<port>/?code=<auth_code>&state=<state>.

  5. Code Extraction: The temporary server's callback handler extracts the authorization code from query parameters, closes the HTTP listener, and yields a waiting event to the UI.

  6. Token Exchange: The helper POSTs the authorization code to https://auth.kimi.ai/token (using built-in client credentials) and receives an access token and optional refresh token in the response.

  7. Credential Persistence: The access token is stored in the CLI configuration under config.providers[KIMI_CODE_PLATFORM_ID] with the structure { "access_token": "...", "expires_at": <epoch> }. The helper yields a success event.

  8. Shell Reload: The login() function records a telemetry event and raises Reload to restart the shell with the new authentication context applied.

Core OAuth Implementation Files

Understanding the source code locations is essential for extending or debugging the authentication flow:

  • src/kimi_cli/auth/oauth.py: Contains login_kimi_code() and logout_kimi_code() async generators that emit waiting, success, or error events during the authentication lifecycle.

  • src/kimi_cli/ui/shell/oauth.py: Houses the login() and logout() shell commands that wrap the OAuth helpers and handle UI event streaming.

  • src/kimi_cli/web/auth.py: Implements AuthMiddleware which performs timing-safe token comparison via verify_token() and returns 401 Unauthorized for invalid or missing credentials.

  • src/kimi_cli/auth/platforms.py: Defines platform-specific constants including KIMI_CODE_PLATFORM_ID and authorization endpoint URL builders.

  • src/kimi_cli/config.py: Handles global configuration persistence, storing provider tokens and managing the providers dictionary structure.

Practical Code Examples

Interactive Login Command

When working in the Kimi shell, users trigger authentication with a single command:


# In the interactive Kimi shell

>>> login

# Internally executes:

#   - Platform selection (KIMI_CODE_PLATFORM_ID)

#   - Browser opening to https://auth.kimi.ai/authorize

#   - Temporary uvicorn server startup on localhost

#   - Token exchange at https://auth.kimi.ai/token

#   - Configuration update with access_token and expires_at

#   - Shell reload via Reload exception

Programmatic Login Implementation

Third-party tools can integrate the OAuth flow using the public async generator API:

from kimi_cli.auth.oauth import login_kimi_code
from kimi_cli.config import load_config

async def perform_login():
    cfg = load_config()
    async for event in login_kimi_code(cfg):
        if event.type == "success":
            print("✅ Successfully authenticated with Kimi platform")
        elif event.type == "error":
            print(f"❌ Authentication failed: {event.message}")

Accessing Stored Credentials

Retrieve the active access token from the configuration store:

from kimi_cli.config import load_config
from kimi_cli.auth.platforms import KIMI_CODE_PLATFORM_ID

cfg = load_config()
provider = cfg.providers.get(KIMI_CODE_PLATFORM_ID)
access_token = provider["access_token"] if provider else None
print(f"Current token: {access_token}")

Logout Implementation

Terminate the session by removing stored credentials:

from kimi_cli.auth.oauth import logout_kimi_code
from kimi_cli.config import load_config

async def perform_logout():
    cfg = load_config()
    async for event in logout_kimi_code(cfg):
        print(event.message)  # Outputs success or error status

API Token Validation

After authentication, every API request passes through the AuthMiddleware implemented in src/kimi_cli/web/auth.py. The middleware extracts bearer tokens from the Authorization: Bearer <token> header (or ?token=<token> query parameter for GET requests) and validates them using constant-time comparison via verify_token().

If the token is missing, malformed, or invalid, the middleware immediately returns a 401 Unauthorized response. Valid tokens allow the request to proceed to the underlying API handlers. This validation occurs on every request, ensuring continuous security even for long-running CLI sessions.

Summary

  • Kimi CLI uses OAuth 2.0 Authorization Code flow with a temporary local callback server to bridge browser-based authentication and CLI environments.
  • Three architectural layers (UI, OAuth helpers, and Web middleware) separate concerns between user interaction, protocol implementation, and request validation.
  • Key implementation files include src/kimi_cli/auth/oauth.py for flow logic and src/kimi_cli/web/auth.py for token validation.
  • Tokens are stored in config.providers[KIMI_CODE_PLATFORM_ID] with expiration timestamps and validated on every API call.
  • Async generators emit structured events (waiting, success, error) enabling real-time UI feedback during authentication.

Frequently Asked Questions

What OAuth 2.0 grant type does Kimi CLI implement?

Kimi CLI implements the Authorization Code grant type as defined in RFC 6749. The flow initiates in the browser, returns an authorization code to a temporary local server listening on localhost, and exchanges that code for an access token at the https://auth.kimi.ai/token endpoint. This approach keeps client credentials and tokens out of the browser history while enabling secure CLI authentication.

Where does Kimi CLI store access tokens locally?

Access tokens are persisted in the user configuration file managed by src/kimi_cli/config.py, specifically within the providers dictionary under the key KIMI_CODE_PLATFORM_ID. The stored object includes the access_token string and an expires_at Unix timestamp. This configuration is typically stored in the user's home directory and is distinct from shell environment variables for security isolation.

How does Kimi CLI handle token expiration and refresh?

The current implementation stores an expires_at timestamp alongside the access token in the provider configuration. While the raw token exchange may include refresh tokens in the OAuth response, the CLI checks expiration timestamps during API request validation in AuthMiddleware. Users must re-run kimi login to obtain fresh credentials when tokens expire, as the flow prioritizes security over automatic background refresh in the current implementation.

Is the temporary local callback server secure?

Yes, the temporary server implemented in src/kimi_cli/auth/oauth.py uses several security measures: it binds only to localhost (preventing external network access), uses a random ephemeral port, validates the state parameter to prevent CSRF attacks, and shuts down immediately after receiving the first callback. The server runs via uvicorn in a dedicated async context, ensuring the authorization code is captured only by the local CLI process and never exposed to external networks.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →