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.
- π 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
- Bun >= 1.0.0
- Google OAuth credentials (Client ID and Secret)
- OpenCode server running (for proxying)
-
Install dependencies:
bun install
-
Create
.envfile:SESSION_SECRET=your-very-long-secret-key-at-least-32-characters GOOGLE_REDIRECT_CLIENT_ID=your-client-id GOOGLE_REDIRECT_CLIENT_SECRET=your-client-secret GOOGLE_REDIRECT_URI=http://localhost:4096/auth/google/callback PORT=4096 TARGET_HOST=127.0.0.1 TARGET_PORT=4097
-
Run the server:
bun run dev # Development with watch bun run start # Production
-
Authenticate:
- Visit
http://localhost:4096/auth/google/start - Complete Google OAuth flow
- You'll be redirected back with a session cookie
- Visit
| Variable | Required | Default | Description |
|---|---|---|---|
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_URI |
β | http://localhost:4096/auth/google/callback |
OAuth redirect URI |
PORT |
β | 4096 |
Proxy server port |
TARGET_HOST |
β | 127.0.0.1 |
Upstream OpenCode server host |
TARGET_PORT |
β | 4097 |
Upstream OpenCode server port |
TOKEN_PATH |
β | ~/.opencode-gateway/google-auth.json |
Token storage path |
SESSION_COOKIE_NAME |
β | opencode_session |
Session cookie name |
COOKIE_SECURE |
β | Auto-detect | Use secure cookies (HTTPS) |
PROXY_TO_SERVER_SECRET |
β | - | Optional secret for upstream authentication |
TRUST_PROXY |
β | false |
Trust proxy headers (X-Forwarded-*) |
# Required
SESSION_SECRET=your-very-long-secret-key-at-least-32-characters-long
GOOGLE_REDIRECT_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
GOOGLE_REDIRECT_CLIENT_SECRET=your-google-client-secret
# Optional - defaults shown
GOOGLE_REDIRECT_URI=http://localhost:4096/auth/google/callback
PORT=4096
TARGET_HOST=127.0.0.1
TARGET_PORT=4097
TOKEN_PATH=~/.opencode-gateway/google-auth.json
SESSION_COOKIE_NAME=opencode_session
COOKIE_SECURE=true
TRUST_PROXY=false| Endpoint | Method | Description |
|---|---|---|
/health |
GET | Health check |
/global/health |
GET | Global health check |
/auth/google/start |
GET | Begin OAuth flow (query: ?project=<id>) |
/auth/google/callback |
GET | OAuth callback |
/auth/google/config |
GET | OAuth configuration info |
/debug/sse-test |
GET | SSE test UI |
/debug/sse |
GET | SSE test endpoint |
| Endpoint | Method | Description |
|---|---|---|
/ |
* | Proxied to upstream OpenCode server |
/auth/google/token |
GET | Get stored OAuth token |
/logs |
GET | Log viewer UI (HTML) or log streaming (SSE) |
/logs/stream |
GET | Log streaming (SSE) to /global/event |
- User visits
/auth/google/startβ Redirected to Google OAuth - Google redirects back to
/auth/google/callbackwith authorization code - Proxy exchanges code for tokens using PKCE verification
- Tokens stored locally and secure session cookie set
- Subsequent requests with valid session cookie are proxied to OpenCode
βββββββββββ ββββββββββββ βββββββββββ βββββββββββββββ
β Browser β ββββββ> β Proxy β ββββββ> β Google β ββββββ> β Proxy β
β β <ββββββ β β <ββββββ β OAuth β <ββββββ β (callback) β
βββββββββββ ββββββββββββ βββββββββββ βββββββββββββββ
β β β
β β β
β βΌ βΌ
β [Session Cookie] [Store Tokens]
β β β
ββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
[Authenticated Requests]
β
βΌ
[OpenCode Server]
The proxy provides real-time log streaming via Server-Sent Events (SSE).
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
const eventSource = new EventSource('/logs/stream', {
withCredentials: true
})
eventSource.onmessage = (event) => {
const logEntry = JSON.parse(event.data)
console.log(logEntry)
}
eventSource.onerror = (error) => {
console.error('SSE connection error:', error)
}- β Automatic reconnection on connection loss
- β Real-time log streaming
- β Structured log format
- β
Supports
Last-Event-IDfor reconnection
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
- RequestContext Pattern: Dependency injection for testability
- Core/Adapters Separation: Pure logic vs side effects
- Zero Duplication: All shared logic in reusable modules
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
bun testThe test suite includes unit tests for core modules (auth, session, config, http-utils) with test helpers for RequestContext mocking.
- β 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
- Use strong secrets: At least 32 characters for
SESSION_SECRET - HTTPS in production: Set
COOKIE_SECURE=truefor HTTPS - Environment variables: Store secrets in
.env, not in code - Token storage: Keep token file secure (default:
~/.opencode-gateway/)
- Ensure
.envhasSESSION_SECRETset - Or set it as an environment variable
- Minimum 32 characters recommended
- Check
GOOGLE_REDIRECT_CLIENT_IDandGOOGLE_REDIRECT_CLIENT_SECRET - Verify credentials in Google Cloud Console
- Ensure redirect URI matches exactly
- Ensure session cookie is sent with upgrade request
- Check that upstream server supports WebSocket
- Verify proxy is handling upgrade requests correctly
- Verify
TARGET_HOSTandTARGET_PORTare correct - Ensure OpenCode server is running
- Check firewall/network settings
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.
MIT License - see LICENSE file for details
Built with:
- Bun - Fast JavaScript runtime
- http-proxy - HTTP proxying
- TypeScript - Type safety