Skip to content

Conversation

Copy link

Copilot AI commented Oct 2, 2025

Overview

This PR implements configurable API client key authentication to enable safe exposure of the copilot-api server to the open web. The feature is fully backward compatible—when no API keys are configured, the server operates without authentication as before.

Problem

The server currently has no authentication mechanism, making it unsafe to expose to the public internet. Users wanting to deploy this as a publicly accessible service or share it across multiple clients need a way to control access.

Solution

Added a simple yet effective API key authentication system that:

  • Uses industry-standard authentication: Accepts API keys via the Authorization header in standard OpenAI format (Bearer <key> or just <key>)
  • Supports multiple clients: Comma-separated API keys allow different keys for different users/applications
  • Protects the right endpoints: All API endpoints (/v1/chat/completions, /v1/models, /v1/embeddings, /v1/messages) require authentication when keys are configured
  • Keeps monitoring accessible: Public endpoints (/, /usage, /token) remain accessible without authentication
  • Maintains backward compatibility: When --api-keys is not provided, the server operates without authentication (no breaking changes)

Usage

Start the server with API keys:

# Single key
npx copilot-api@latest start --api-keys mykey123

# Multiple keys for different clients
npx copilot-api@latest start --api-keys client1-key,client2-key,admin-key

# Combined with other options
npx copilot-api@latest start --api-keys mykey --rate-limit 30 --port 8080

Make authenticated requests:

# Using curl
curl -H "Authorization: Bearer mykey123" http://localhost:4141/v1/models

# Using Python OpenAI client
from openai import OpenAI
client = OpenAI(api_key="mykey123", base_url="http://localhost:4141")
response = client.chat.completions.create(
    model="gpt-4o-2024-05-13",
    messages=[{"role": "user", "content": "Hello!"}]
)

Configure Claude Code with authentication:

{
  "env": {
    "ANTHROPIC_BASE_URL": "http://localhost:4141",
    "ANTHROPIC_AUTH_TOKEN": "mykey123",
    "ANTHROPIC_MODEL": "gpt-4.1",
    "ANTHROPIC_SMALL_FAST_MODEL": "gpt-4.1"
  }
}

Implementation Details

  • Middleware-based approach: Uses Hono's middleware system for clean, efficient authentication
  • Minimal code footprint: Core middleware is only 45 lines
  • Stateless: No session management needed—simple string comparison
  • Granular control: Applied at the route level, allowing public and protected endpoints to coexist
  • Proper error responses: Returns standard 401 Unauthorized with descriptive error messages

Testing

Added comprehensive test coverage:

  • 11 unit tests for authentication middleware (valid/invalid keys, multiple keys, edge cases)
  • 12 integration tests for complete authentication flow across all endpoints
  • All 49 tests passing (26 existing + 23 new)
  • Build and lint checks passing

Files Changed

  • src/lib/auth-middleware.ts - New authentication middleware
  • src/lib/state.ts - Added apiKeys state field
  • src/server.ts - Applied middleware to protected routes
  • src/start.ts - Added --api-keys CLI option
  • README.md - Comprehensive documentation with examples
  • tests/auth-middleware.test.ts - Unit tests
  • tests/api-key-integration.test.ts - Integration tests

Security Considerations

  • API keys are case-sensitive for security
  • Keys are validated on every request to protected endpoints
  • Clear error messages distinguish between missing and invalid keys
  • Public monitoring endpoints remain accessible for operational visibility

Example: Production Deployment

# Generate strong API keys
KEY1=$(openssl rand -base64 32)
KEY2=$(openssl rand -base64 32)

# Start server with authentication
npx copilot-api@latest start \
  --api-keys "$KEY1,$KEY2" \
  --port 4141 \
  --rate-limit 30 \
  --wait

# Distribute keys to authorized clients
echo "Client 1 API Key: $KEY1"
echo "Client 2 API Key: $KEY2"

This implementation enables safe deployment to public infrastructure while maintaining the simplicity and ease-of-use that makes copilot-api great for local development.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • aur.archlinux.org
    • Triggering command: node ./dist/main.js start --help (dns block)
    • Triggering command: bun test tests/api-key-integration.test.ts (dns block)
    • Triggering command: bun test (dns block)
  • https://api.github.com/copilot_internal/user
    • Triggering command: bun test tests/api-key-integration.test.ts (http block)
    • Triggering command: bun test (http block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

Add configurable API client keys to pass alongside the request in the usual openai api type request for clients to be able to authenticate themselves to this server; to allow exposing to the open web safely


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Add configurable API client keys to pass alongside the request in the usual openai api type request for clients to be able to authenticate themselves to this server; to allow exposing to the open web safely Add configurable API key authentication for secure web exposure Oct 2, 2025
Copilot AI requested a review from dronesflier October 2, 2025 12:52
Copy link
Owner

@dronesflier dronesflier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@dronesflier dronesflier marked this pull request as ready for review October 2, 2025 13:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants