A standalone Bun application that acts as a transparent OAuth proxy for the Gemini API. It handles PKCE-based OAuth authentication, automatic token refresh, and request/response transformation - allowing Vercel AI SDK clients to use OAuth-authenticated Gemini APIs without managing tokens themselves.
Inspired by opencode-gemini-auth - a Gemini OAuth plugin for the Opencode CLI.
- OAuth PKCE Flow - Secure authentication with Google using PKCE
- Automatic Token Refresh - Tokens are refreshed automatically before expiry
- Request/Response Transformation - Handles Code Assist API wrapping/unwrapping
- Web UI - Simple dark-themed UI for login/logout and status monitoring
- SQLite Storage - Tokens persist across restarts
- Bun runtime installed
- A Google account with access to Gemini
git clone https://github.com/ygncode/gemini-auth-proxy.git
cd gemini-auth-proxy
bun installbun run startThe server will start on http://localhost:8888.
For persistent background operation, use pm2:
# Install pm2 globally (if not already installed)
npm install -g pm2
# Start the proxy in background
pm2 start bun --name "gemini-proxy" -- run start
# Useful pm2 commands
pm2 status # Check running status
pm2 logs gemini-proxy # View logs
pm2 restart gemini-proxy # Restart server
pm2 stop gemini-proxy # Stop server
pm2 delete gemini-proxy # Remove from pm2
# Auto-start on system boot (optional)
pm2 startup
pm2 save# Build and start
docker-compose up -d
# View logs
docker-compose logs -f
# Stop
docker-compose downThe server will be available at http://localhost:8888.
Note: The container uses
network_mode: hostso it binds directly to the host's network. This allows other Docker containers (also using host networking) to access it vialocalhost:8888.
- Open
http://localhost:8888/uiin your browser - Click "Login with Google"
- Complete the OAuth flow in your browser
- You're now authenticated!
import { createGoogleGenerativeAI } from "@ai-sdk/google";
import { generateText } from "ai";
const google = createGoogleGenerativeAI({
baseURL: "http://localhost:8888/codeassist",
apiKey: "proxy", // Placeholder - proxy handles real auth
});
const model = google("gemini-2.5-flash");
const result = await generateText({
model,
prompt: "Hello!",
});
console.log(result.text);| Endpoint | Description |
|---|---|
/codeassist/* |
Routes through Code Assist API with OAuth |
/gemini/* |
Same as above - alternative path for organization |
/ui |
Web UI for login/status/logout |
Both /codeassist/* and /gemini/* work identically - they're provided for organizational flexibility in your code.
Run the included examples:
# Code Assist endpoint example
bun run example:code-assist
# Gemini endpoint example
bun run example:standard| Script | Description |
|---|---|
bun run start |
Start the proxy server |
bun run dev |
Start with hot reload |
bun run example:code-assist |
Run Code Assist example |
bun run example:standard |
Run Gemini example |
┌─────────────────────┐ ┌──────────────────────────────┐ ┌─────────────────────┐
│ Vercel AI SDK │ │ gemini-auth-proxy │ │ Google APIs │
│ (your app) │ │ localhost:8888 │ │ │
│ │ │ │ │ │
│ baseURL: │─────>│ /codeassist/* or /gemini/* │─────>│ cloudcode-pa │
│ localhost:8888/ │ │ │ │ .googleapis.com │
│ codeassist │ │ • OAuth token injection │ │ │
│ │ │ • Request transformation │ │ │
│ apiKey: "proxy" │ │ • Response unwrapping │ │ │
└─────────────────────┘ │ • Auto token refresh │ └─────────────────────┘
└──────────────────────────────┘
- Your app sends requests to the proxy with a placeholder API key
- Proxy injects the real OAuth Bearer token
- Proxy transforms requests to Code Assist API format
- Proxy unwraps responses back to standard Gemini format
- If token is expired, proxy automatically refreshes it
gemini-auth-proxy/
├── src/
│ ├── index.ts # Entry point
│ ├── server.ts # Bun HTTP server
│ ├── constants.ts # OAuth credentials, endpoints
│ ├── auth/ # OAuth, token refresh, cache
│ ├── transform/ # Request/response transformation
│ ├── project/ # Managed project discovery
│ ├── routes/ # UI and proxy handlers
│ ├── ui/ # HTMX templates and styles
│ └── db/ # SQLite storage
├── examples/ # Usage examples
└── data/ # SQLite database (gitignored)
The proxy uses Google's Gemini CLI OAuth credentials by default. No additional configuration is required.
| Variable | Description | Default |
|---|---|---|
| None required | Proxy works out of the box | - |
Tokens are stored in data/auth.db (SQLite). This file is gitignored and contains:
- Refresh token
- Access token
- Token expiry
- User email
- Project ID
Visit http://localhost:8888/ui and login with Google.
The proxy automatically refreshes tokens. If you see expiry errors, try logging out and back in.
Kill the existing process:
lsof -ti:8888 | xargs kill -9This project is inspired by and adapts code from opencode-gemini-auth, which provides Gemini OAuth authentication for the Opencode CLI. The OAuth flow, token refresh logic, and request/response transformation patterns are derived from that project.
MIT