# OAuth and API-Key Authentication Flows in Qwen Code: A Complete Technical Comparison

> Compare OAuth device-code flow and API-key authentication for Qwen Code. Understand differences and integration options for Qwen hosted models and third-party providers.

- Repository: [Qwen/qwen-code](https://github.com/qwenlm/qwen-code)
- Tags: deep-dive
- Published: 2026-02-19

---

**Qwen Code supports OAuth via a browser-based device-code flow that caches credentials locally for Qwen-hosted models, while API-key authentication enables direct integration with third-party providers like OpenAI and Anthropic through environment variables or CLI flags.**

When configuring **Qwen Code**, the open-source coding assistant from **QwenLM**, developers must choose between two distinct **OAuth and API-key authentication flows**. Understanding the architectural differences between these mechanisms is essential for securing your connection to language model services while optimizing for your specific deployment environment, provider preferences, and quota requirements.

## How OAuth Authentication Works in Qwen Code

The OAuth implementation provides a zero-configuration authentication experience specifically designed for Qwen-hosted language models.

### Device-Code Flow Implementation

The core OAuth logic resides in [`packages/core/src/qwen/qwenOAuth2.ts`](https://github.com/QwenLM/qwen-code/blob/main/packages/core/src/qwen/qwenOAuth2.ts). This module implements the complete device-code authorization sequence:

1. The CLI requests a device code from `https://chat.qwen.ai/api/v1/oauth2/device/code`
2. The user visits the verification URL in a browser to authorize the device
3. The CLI polls the token endpoint until authorization completes

```typescript
const response = await fetch(QWEN_OAUTH_DEVICE_CODE_ENDPOINT, {
  method: 'POST',
  body: objectToUrlEncoded({
    client_id: QWEN_OAUTH_CLIENT_ID,
    scope: QWEN_OAUTH_SCOPE,
    // …
  }),
});

```

### Token Persistence and Refresh

Once authenticated, the `SharedTokenManager` class persists credentials to `~/.qwen/.qwen/oauth_creds.json`. This file stores the `access_token`, `refresh_token`, and expiry timestamps. The system automatically refreshes expired tokens using the stored refresh token, ensuring seamless authentication across CLI sessions without requiring repeated browser logins.

### MCP Transport Integration

The OAuth token integrates into Model Context Protocol (MCP) transports via [`packages/core/src/mcp/oauth-provider.ts`](https://github.com/QwenLM/qwen-code/blob/main/packages/core/src/mcp/oauth-provider.ts). The `createTransportWithOAuth` function injects the `Authorization: Bearer <token>` header into all requests to Qwen-hosted models, handling authentication transparently for subsequent API calls.

## How API-Key Authentication Works in Qwen Code

API-key authentication provides a flexible, non-interactive method for connecting to third-party language model providers.

### Environment Variable Configuration

API-key validation logic lives in [`packages/cli/src/config/auth.ts`](https://github.com/QwenLM/qwen-code/blob/main/packages/cli/src/config/auth.ts). This module checks for provider-specific environment variables defined in the `DEFAULT_ENV_KEYS` mapping:

```typescript
const DEFAULT_ENV_KEYS: Record<string, string> = {
  [AuthType.USE_OPENAI]: 'OPENAI_API_KEY',
  [AuthType.USE_ANTHROPIC]: 'ANTHROPIC_API_KEY',
  // …
};

```

When no key is found, the `getApiKeyError` function generates a descriptive error message indicating the required environment variable or the `settings.security.auth.apiKey` fallback location.

### CLI Flag Overrides

The configuration system in [`packages/cli/src/config/config.ts`](https://github.com/QwenLM/qwen-code/blob/main/packages/cli/src/config/config.ts) registers provider-specific CLI flags such as `--openai-api-key`, `--anthropic-api-key`, and `--google-api-key`. These flags directly set the corresponding environment variable for the current process, overriding any existing configuration.

### Custom Environment Keys

Individual model entries can specify custom environment variables via the `envKey` property in [`settings.json`](https://github.com/QwenLM/qwen-code/blob/main/settings.json). The `hasApiKeyForAuth` function checks these custom keys before falling back to the default environment variable mappings, enabling sophisticated multi-account scenarios and enterprise secrets management.

## Key Differences Between OAuth and API-Key Flows

Understanding the architectural distinctions helps determine the appropriate authentication strategy for your specific use case.

### User Interaction Model

**OAuth** requires a one-time browser-based login using the device-code flow. The first run opens a verification page, after which credentials are cached locally. **API-key** authentication operates silently, requiring no interactive steps once the key is configured in the environment or settings file.

### Credential Storage

OAuth persists encrypted tokens in `~/.qwen/.qwen/oauth_creds.json` managed by the `SharedTokenManager` class. API-keys remain in process environment variables or the [`settings.json`](https://github.com/QwenLM/qwen-code/blob/main/settings.json) file, never persisting to dedicated credential cache files unless explicitly configured by the user.

### Supported Model Providers

OAuth exclusively supports built-in Qwen models via `AuthType.QWEN_OAUTH`. API-key authentication supports diverse providers including OpenAI-compatible endpoints, Anthropic, Gemini, and Vertex AI through `AuthType.USE_OPENAI`, `USE_ANTHROPIC`, and related variants.

### Quota and Billing

OAuth provides free quota (approximately 60 requests per minute, 1,000 requests per day) enforced by Qwen's backend infrastructure. API-key usage follows the billing and rate limits of the respective third-party provider, offering unlimited scaling based on your subscription plan.

## Practical Configuration Examples

### OAuth Setup

No configuration is required for OAuth. Simply execute:

```bash
qwen

```

The CLI automatically initiates the device-code flow on first use, opening your browser to `https://chat.qwen.ai` for authorization. Subsequent runs use the cached credentials from `~/.qwen/.qwen/oauth_creds.json`.

### API-Key Setup for OpenAI

Configure via environment variable:

```bash
export OPENAI_API_KEY="sk-xxxxxxxxxxxxxxxx"
qwen --openai-api-key $OPENAI_API_KEY ask "Write a Python script"

```

Or configure via [`settings.json`](https://github.com/QwenLM/qwen-code/blob/main/settings.json):

```json
{
  "modelProviders": {
    "openai": [
      {
        "id": "gpt-4o",
        "envKey": "OPENAI_API_KEY",
        "baseUrl": "https://api.openai.com/v1"
      }
    ]
  },
  "security": {
    "auth": { "selectedType": "openai" }
  }
}

```

### Programmatic SDK Usage

```typescript
import { createQuery } from '@qwen-code/qwen-code-sdk';
import { AuthType } from '@qwen-code/qwen-code-core';

// OAuth for Qwen models
await createQuery({
  authType: AuthType.QWEN_OAUTH,
  model: 'qwen-turbo',
}).run('Summarize this repository.');

// API-key for OpenAI
await createQuery({
  authType: AuthType.USE_OPENAI,
  model: 'gpt-4o',
}).run('Translate to French.');

```

## Summary

- **OAuth** provides a browser-based device-code flow with automatic token persistence in `~/.qwen/.qwen/oauth_creds.json`, supporting only Qwen-hosted models with free quota limits (60 req/min, 1,000 req/day).
- **API-key** authentication enables integration with OpenAI, Anthropic, Gemini, and other providers through environment variables or CLI flags, offering flexible billing and rate limits without interactive login steps.
- The **OAuth implementation** resides in [`packages/core/src/qwen/qwenOAuth2.ts`](https://github.com/QwenLM/qwen-code/blob/main/packages/core/src/qwen/qwenOAuth2.ts) and [`packages/core/src/mcp/oauth-provider.ts`](https://github.com/QwenLM/qwen-code/blob/main/packages/core/src/mcp/oauth-provider.ts), while **API-key validation** is handled by [`packages/cli/src/config/auth.ts`](https://github.com/QwenLM/qwen-code/blob/main/packages/cli/src/config/auth.ts) with CLI flags defined in [`packages/cli/src/config/config.ts`](https://github.com/QwenLM/qwen-code/blob/main/packages/cli/src/config/config.ts).
- Choose **OAuth** for zero-configuration access to Qwen models with automatic credential management, or **API-key** for multi-provider flexibility and enterprise secrets management requirements.

## Frequently Asked Questions

### Can I use OAuth with third-party providers like OpenAI?

No. The OAuth flow implemented in [`packages/core/src/qwen/qwenOAuth2.ts`](https://github.com/QwenLM/qwen-code/blob/main/packages/core/src/qwen/qwenOAuth2.ts) exclusively supports Qwen-hosted models through `AuthType.QWEN_OAUTH`. Third-party providers such as OpenAI, Anthropic, and Gemini require API-key authentication via `AuthType.USE_OPENAI` and related variants, as these providers do not support Qwen's specific device-code OAuth implementation.

### Where are OAuth credentials stored on my machine?

OAuth credentials are cached in `~/.qwen/.qwen/oauth_creds.json` by the `SharedTokenManager` class. This file contains the access token, refresh token, and expiry timestamps. The system automatically refreshes expired tokens using the stored refresh token, ensuring seamless authentication across CLI sessions without requiring repeated browser logins.

### How do I switch from OAuth to API-key authentication?

To switch from OAuth to API-key authentication, set the appropriate environment variable for your chosen provider (e.g., `export OPENAI_API_KEY="sk-xxx"`) or pass the corresponding CLI flag (e.g., `--openai-api-key`). Then update your [`settings.json`](https://github.com/QwenLM/qwen-code/blob/main/settings.json) to change `security.auth.selectedType` to the desired provider (e.g., `"openai"`). The CLI will bypass the OAuth flow and use the API key directly.

### Is OAuth more secure than API-key authentication?

Both methods offer different security trade-offs. OAuth stores tokens in a dedicated credential file (`~/.qwen/.qwen/oauth_creds.json`) with automatic refresh, reducing the risk of exposing long-lived credentials in shell history or environment variables. However, API-key authentication allows integration with enterprise secrets management systems and avoids storing credentials in local files unless explicitly configured. For shared or ephemeral environments, API-keys injected via environment variables are often preferred, while OAuth provides better user experience for individual developers using Qwen models.