Skip to content

Repository files navigation

OpenCode Gateway

A lightweight, secure reverse proxy with Google OAuth authentication for OpenCode. Protects your OpenCode server by enforcing authentication before proxying requests.

Note: This project is not built by the OpenCode team and is not affiliated with OpenCode in any way.

BunTypeScriptLicense

✨ Features

  • 🔐 Google OAuth 2.0 - PKCE flow for secure authentication
  • 🍪 Session Management - HMAC-signed secure session cookies
  • 🔄 Reverse Proxy - Seamless forwarding to upstream OpenCode server
  • 🌐 WebSocket Support - Full WebSocket proxying with authentication
  • 📡 SSE Streaming - Real-time log streaming with automatic reconnection
  • 🏥 Health Checks - Built-in health monitoring endpoints
  • 🛠️ Debug Tools - Log viewer UI and SSE test tools
  • 🏗️ Modular Architecture - Clean, maintainable, testable codebase

🚀 Quick Start

Prerequisites

  • Bun >= 1.0.0
  • Google OAuth credentials (Client ID and Secret)
  • OpenCode server running (for proxying)

Installation

  1. Install dependencies:

    bun install
  2. Create .env file:

    SESSION_SECRET=your-very-long-secret-key-at-least-32-charactersGOOGLE_REDIRECT_CLIENT_ID=your-client-idGOOGLE_REDIRECT_CLIENT_SECRET=your-client-secretGOOGLE_REDIRECT_URI=http://localhost:4096/auth/google/callbackPORT=4096TARGET_HOST=127.0.0.1TARGET_PORT=4097
  3. Run the server:

    bun run dev # Development with watch
    bun run start # Production
  4. Authenticate:

    • Visit http://localhost:4096/auth/google/start
    • Complete Google OAuth flow
    • You'll be redirected back with a session cookie

🔧 Configuration

Environment Variables

VariableRequiredDefaultDescription
SESSION_SECRET-Secret key for session signing (min 32 chars recommended)
GOOGLE_REDIRECT_CLIENT_ID-Google OAuth Client ID
GOOGLE_REDIRECT_CLIENT_SECRET-Google OAuth Client Secret
GOOGLE_REDIRECT_URIhttp://localhost:4096/auth/google/callbackOAuth redirect URI
PORT4096Proxy server port
TARGET_HOST127.0.0.1Upstream OpenCode server host
TARGET_PORT4097Upstream OpenCode server port
TOKEN_PATH~/.opencode-gateway/google-auth.jsonToken storage path
SESSION_COOKIE_NAMEopencode_sessionSession cookie name
COOKIE_SECUREAuto-detectUse secure cookies (HTTPS)
PROXY_TO_SERVER_SECRET-Optional secret for upstream authentication
TRUST_PROXYfalseTrust proxy headers (X-Forwarded-*)

Example .env File

# RequiredSESSION_SECRET=your-very-long-secret-key-at-least-32-characters-longGOOGLE_REDIRECT_CLIENT_ID=your-google-client-id.apps.googleusercontent.comGOOGLE_REDIRECT_CLIENT_SECRET=your-google-client-secret# Optional - defaults shownGOOGLE_REDIRECT_URI=http://localhost:4096/auth/google/callbackPORT=4096TARGET_HOST=127.0.0.1TARGET_PORT=4097TOKEN_PATH=~/.opencode-gateway/google-auth.jsonSESSION_COOKIE_NAME=opencode_sessionCOOKIE_SECURE=trueTRUST_PROXY=false

🌐 API Endpoints

Public Endpoints

EndpointMethodDescription
/healthGETHealth check
/global/healthGETGlobal health check
/auth/google/startGETBegin OAuth flow (query: ?project=<id>)
/auth/google/callbackGETOAuth callback
/auth/google/configGETOAuth configuration info
/debug/sse-testGETSSE test UI
/debug/sseGETSSE test endpoint

Authenticated Endpoints

EndpointMethodDescription
/*Proxied to upstream OpenCode server
/auth/google/tokenGETGet stored OAuth token
/logsGETLog viewer UI (HTML) or log streaming (SSE)
/logs/streamGETLog streaming (SSE) to /global/event

🔄 How It Works

  1. User visits/auth/google/start → Redirected to Google OAuth
  2. Google redirects back to /auth/google/callback with authorization code
  3. Proxy exchanges code for tokens using PKCE verification
  4. Tokens stored locally and secure session cookie set
  5. Subsequent requests with valid session cookie are proxied to OpenCode

Authentication Flow

┌─────────┐ ┌──────────┐ ┌─────────┐ ┌─────────────┐
│ Browser │ ──────> │ Proxy │ ──────> │ Google │ ──────> │ Proxy │
│ │ <────── │ │ <────── │ OAuth │ <────── │ (callback) │
└─────────┘ └──────────┘ └─────────┘ └─────────────┘
│ │ │
│ │ │
│ ▼ ▼
│ [Session Cookie] [Store Tokens]
│ │ │
└────────────────────┼──────────────────────────────────────────┘
│
▼
[Authenticated Requests]
│
▼
[OpenCode Server]

📡 Log Streaming

The proxy provides real-time log streaming via Server-Sent Events (SSE).

Web UI

Visit http://localhost:4096/logs after authenticating for a terminal-style log viewer with:

  • Real-time log streaming
  • Color-coded log levels
  • Auto-scroll to latest entries
  • Clear logs functionality

API Usage

consteventSource=newEventSource('/logs/stream',{withCredentials: true})eventSource.onmessage=(event)=>{constlogEntry=JSON.parse(event.data)console.log(logEntry)}eventSource.onerror=(error)=>{console.error('SSE connection error:',error)}

Features

  • ✅ Automatic reconnection on connection loss
  • ✅ Real-time log streaming
  • ✅ Structured log format
  • ✅ Supports Last-Event-ID for reconnection

🏗️ Architecture

The proxy uses a modular architecture with clear separation of concerns:

src/
├── core/ # Pure logic (auth, session, proxy decisions)
├── adapters/ # Runtime implementations (logger, storage, proxy)
├── middleware/ # High-level coordination (auth flow)
└── views/ # HTML templates

Key Design Patterns

  • RequestContext Pattern: Dependency injection for testability
  • Core/Adapters Separation: Pure logic vs side effects
  • Zero Duplication: All shared logic in reusable modules

🧪 Development

Project Structure

opencode-gateway/
├── proxy.ts # Main entry point
├── src/
│ ├── types.ts # Type definitions
│ ├── config.ts # Configuration loader
│ ├── core/ # Pure logic modules
│ │ ├── auth.ts # OAuth & PKCE
│ │ ├── session.ts # Session management
│ │ ├── proxy.ts # Proxy logic
│ │ ├── headers.ts # Security headers
│ │ └── http-utils.ts # HTTP utilities
│ ├── adapters/ # Implementations
│ │ ├── logger/ # Logging adapters
│ │ ├── storage/ # Token storage
│ │ └── proxy/ # Proxy server
│ ├── middleware/ # Coordination
│ │ └── auth-flow.ts # Auth flow
│ └── views/ # HTML templates
└── tests/ # Test suite

Running Tests

bun test

The test suite includes unit tests for core modules (auth, session, config, http-utils) with test helpers for RequestContext mocking.

🔒 Security

Features

  • PKCE Flow: Prevents authorization code interception
  • HMAC Sessions: Tamper-proof session cookies
  • State TTL: OAuth state expires after 10 minutes
  • Secret Validation: Warnings for weak secrets
  • Hop-by-Hop Headers: Proper header stripping
  • Security Headers: HSTS, CSP, X-Frame-Options

Best Practices

  1. Use strong secrets: At least 32 characters for SESSION_SECRET
  2. HTTPS in production: Set COOKIE_SECURE=true for HTTPS
  3. Environment variables: Store secrets in .env, not in code
  4. Token storage: Keep token file secure (default: ~/.opencode-gateway/)

🐛 Troubleshooting

"SESSION_SECRET is required"

  • Ensure .env has SESSION_SECRET set
  • Or set it as an environment variable
  • Minimum 32 characters recommended

"Google OAuth credentials are required"

  • Check GOOGLE_REDIRECT_CLIENT_ID and GOOGLE_REDIRECT_CLIENT_SECRET
  • Verify credentials in Google Cloud Console
  • Ensure redirect URI matches exactly

WebSocket connections not working

  • Ensure session cookie is sent with upgrade request
  • Check that upstream server supports WebSocket
  • Verify proxy is handling upgrade requests correctly

Can't connect to upstream

  • Verify TARGET_HOST and TARGET_PORT are correct
  • Ensure OpenCode server is running
  • Check firewall/network settings

🤝 Contributing

This is a focused project, but improvements are welcome! Key areas:

  • Integration tests
  • Additional storage adapters
  • Performance optimizations
  • Documentation improvements

See CONTRIBUTING.md for guidelines.

📄 License

MIT License - see LICENSE file for details

🙏 Acknowledgments

Built with:

About

A lightweight, secure reverse proxy with Google OAuth authentication for OpenCode.

Resources

Contributing

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages