JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 60
  • Score
    100M100P100Q86672F
  • License MIT

OAuth 2.0 Device Flow plugin for OpenCode - authenticate with Qwen.ai (PKCE secured, auto token refresh)

Package Exports

  • opencode-qwen-oauth
  • opencode-qwen-oauth/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (opencode-qwen-oauth) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

opencode-qwen-oauth

npm version npm downloads License: MIT CI Status Contributing TypeScript OpenCode Qwen

Qwen OAuth authentication plugin for OpenCode - authenticate with Qwen.ai using OAuth device flow (PKCE).

Features

  • 🔐 OAuth Device Flow - PKCE-secured authentication, works in headless/CI environments
  • 🔄 Automatic Token Refresh - Tokens are refreshed before expiry
  • 💾 Persistent Credentials - Tokens saved to ~/.qwen/oauth_creds.json for persistence across sessions
  • 🌐 Auto Browser Open - Automatically opens browser for authentication
  • 🚀 Easy Install - One-command installation with CLI tool
  • 🎯 Custom Headers - Automatically adds Qwen-specific headers (X-DashScope-*) to API requests
  • ⚙️ Optimized Parameters - Pre-configured temperature and topP settings for Qwen models
  • 🌍 Environment Variables - Exposes Qwen credentials to shell environments
  • ⏱️ Request Throttling - Built-in rate limiting to avoid 429 errors
  • 🏗️ Clean Architecture - Layered design (services, repositories, middleware) for maintainability

Quick Start

Install

# Using npx (recommended)
npx opencode-qwen-oauth install

# Or using bunx
bunx opencode-qwen-oauth install

# Or install manually
npm install opencode-qwen-oauth

The installer will:

  • Add opencode-qwen-oauth to your .opencode/opencode.json plugins
  • Configure the Qwen provider with models

Authenticate

# Start OpenCode
opencode

# Connect to Qwen
/connect

Select "Qwen Code (qwen.ai OAuth)" and follow the device flow instructions.

Use Qwen Models

/model qwen/coder-model

Models

Model Context Output Features
coder-model 1M tokens 64K Optimized for coding
vision-model 128K tokens 32K Vision + language

Configuration

Debug Mode

Enable verbose logging:

QWEN_OAUTH_DEBUG=true opencode

Logs are output to OpenCode's logging system and can be viewed in the OpenCode interface.

Manual Configuration

If you prefer manual setup, add to .opencode/opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "plugin": ["opencode-qwen-oauth"],
  "provider": {
    "qwen": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Qwen Code",
      "options": {
        "baseURL": "https://portal.qwen.ai/v1"
      },
      "models": {
        "coder-model": {
          "id": "coder-model",
          "name": "Qwen Coder",
          "limit": { "context": 1048576, "output": 65536 },
          "modalities": { "input": ["text"], "output": ["text"] }
        },
        "vision-model": {
          "id": "vision-model",
          "name": "Qwen Vision",
          "limit": { "context": 131072, "output": 32768 },
          "modalities": { "input": ["text", "image"], "output": ["text"] },
          "attachment": true
        }
      }
    }
  }
}

CLI Commands

# Install (default)
npx opencode-qwen-oauth install

# Uninstall
npx opencode-qwen-oauth uninstall

# Help
npx opencode-qwen-oauth --help

Diagnostics

Verify Qwen OAuth endpoints are accessible:

curl -I https://chat.qwen.ai/api/v1/oauth2/device/code

This should return 200 OK if endpoints are available.

Troubleshooting

"Device code expired"

Complete the browser login within 15 minutes of starting /connect.

"invalid_grant" error

Your refresh token has expired. Run /connect to re-authenticate.

"Quota exceeded" error

Your free tier limit has been reached. Wait for quota reset or upgrade your account at https://chat.qwen.ai

Provider not showing in /connect

Use the CLI directly:

opencode auth login qwen

Browser doesn't open automatically (Linux)

The plugin tries multiple methods to open your browser:

  1. First tries xdg-open (standard Linux)
  2. Falls back to: google-chrome, firefox, chromium, brave-browser, microsoft-edge

If none work, manually copy the URL shown in the terminal and open it in your browser.

To ensure browser opening works, install xdg-utils:

# Ubuntu/Debian
sudo apt install xdg-utils

# Fedora/RHEL
sudo dnf install xdg-utils

# Arch Linux
sudo pacman -S xdg-utils

Credentials File

Credentials are saved to ~/.qwen/oauth_creds.json (compatible with qwen-code CLI):

~/.qwen/oauth_creds.json

This allows sharing authentication between OpenCode plugin and qwen-code CLI.

Check logs

OpenCode logs can be viewed through the OpenCode interface or by checking the OpenCode log directory.

How It Works

This plugin implements OAuth 2.0 Device Flow (RFC 8628) with PKCE:

  1. Device Code Request - Plugin requests a device code from Qwen OAuth server
  2. User Authorization - User visits the verification URL and enters the user code
  3. Token Polling - Plugin polls for the access token until user authorizes
  4. Token Storage - Tokens are stored in OpenCode's auth system
  5. Auto Refresh - Access tokens are refreshed before expiry

Security & Important Notes

Security Features

  • ✅ Uses PKCE (RFC 7636) for enhanced security
  • ✅ No client secret required (safer for public clients)
  • ✅ Tokens stored in OpenCode's auth system and ~/.qwen/oauth_creds.json for persistence
  • ✅ All OAuth activity logged for auditing
  • ✅ Sensitive data sanitized in logs

Implementation Notes

⚠️ Important: This plugin uses OAuth endpoints that appear to be part of Qwen's web interface (chat.qwen.ai). While the implementation follows standard OAuth 2.0 specifications (RFC 8628 Device Flow + RFC 7636 PKCE), these endpoints are not officially documented in Qwen's public API documentation.

What this means:

  • The OAuth flow works correctly and follows industry standards
  • Endpoints are actively maintained and functional
  • Future changes to Qwen's authentication system may require plugin updates

Verified Working:

  • ✅ OAuth Device Flow: https://chat.qwen.ai/api/v1/oauth2/*
  • ✅ API Endpoint: https://portal.qwen.ai/v1/chat/completions
  • ✅ Token Refresh: Automatic refresh before expiration
  • ✅ OpenAI-Compatible: Uses standard OpenAI API format

Run npm run diagnose to verify endpoint availability at any time.

Development

# Clone and install
git clone https://github.com/dreygur/opencode-qwen-oauth.git
cd opencode-qwen-oauth
npm install

# Build
npm run build

# Watch mode
npm run dev

# Run tests
npm test

# Test locally
npm link
cd /path/to/project
npx opencode-qwen-oauth install

Testing

All tests use Node.js native test runner with tsx:

npm test

29 tests covering:

  • PKCE key pair generation
  • Input validation (URLs, tokens, codes)
  • Data sanitization

Plugin Architecture

This plugin implements multiple OpenCode plugin hooks using a clean, layered architecture:

Hooks Implemented

auth Hook

Provides OAuth device flow authentication with automatic browser opening and token polling. Uses TokenService for token management and CredentialRepository for persistence.

config Hook

Dynamically registers the Qwen provider and available models with OpenCode.

event Hook

Monitors session events for debugging.

chat.headers Hook

Injects custom headers for Qwen API requests:

  • User-Agent: QwenCode/0.10.3 (platform)
  • X-DashScope-CacheControl: enable
  • X-DashScope-UserAgent: QwenCode/0.10.3 (platform)
  • X-DashScope-AuthType: qwen-oauth

chat.params Hook

Optimizes model parameters for Qwen:

  • Temperature: 0.7 (default)
  • Top P: 0.95 (default)

shell.env Hook

Exposes environment variables to shell commands:

  • QWEN_API_BASE_URL - Qwen API endpoint
  • QWEN_PROVIDER - Provider identifier

Architecture

This plugin uses a layered architecture for maintainability:

src/
├── index.ts                    # Plugin entry point (190 lines)
├── types.ts                    # Shared type definitions
├── strategies/
│   └── oauth.strategy.ts       # OAuth Device Flow (RFC 8628)
├── services/
│   └── token.service.ts        # Token management & caching
├── repositories/
│   └── credential.repository.ts # File-based credential storage
├── middleware/
│   ├── auth.middleware.ts      # Auth fetch interceptor
│   ├── rate-limit.middleware.ts # Request throttling
│   └── retry.middleware.ts     # Retry with exponential backoff
├── utils/
│   ├── logger.ts               # Structured logging
│   ├── mutex.ts                # Concurrency control
│   └── pkce.ts                 # PKCE key generation
└── [config, validation, etc.]

Total: ~1,670 lines (refactored from 2,810 lines, -41%)

Note: .opencode/ directory is for local testing only and is not included in the npm package.

License

MIT

Contributing

Contributions are welcome! See CONTRIBUTING.md for guidelines.

  • 🐛 Report bugs via Issues
  • 💡 Suggest features via Discussions
  • 🔧 Submit PRs with tests and documentation

If you find this plugin helpful, please ⭐ star the repo to support the project!