Skip to content

[FEATURE]: Support Bearer token authentication for opencode serve #24874

Closed as not planned

Description

@Edison-A-N

Problem

Currently opencode serve only supports HTTP Basic Auth via OPENCODE_SERVER_PASSWORD. This creates friction in common deployment scenarios:

  1. Reverse proxy / API gateway integration — Most ingress controllers (nginx, Caddy, Traefik, Cloudflare Tunnel) and API gateways use Bearer tokens for upstream authentication. Operators must add a translation layer to convert Bearer → Basic.

  2. Programmatic access — External tools (CI pipelines, scripts, desktop apps) typically pass Authorization: Bearer <token> rather than encoding username:password in base64. The current Basic Auth requirement forces each client to know the username convention ("opencode").

  3. Credential leakage surface — Basic Auth embeds the password in every request header as reversible base64, whereas a Bearer token is opaque and easier to rotate/revoke without changing the underlying secret.

Related issues that reflect current auth pain points:

Current Implementation

From packages/opencode/src/server/middleware.ts:

export const AuthMiddleware: MiddlewareHandler = (c, next) => {
  if (c.req.method === "OPTIONS") return next()
  const password = Flag.OPENCODE_SERVER_PASSWORD
  if (!password) return next()
  const username = Flag.OPENCODE_SERVER_USERNAME ?? "opencode"
  if (c.req.query("auth_token"))
    c.req.raw.headers.set("authorization", `Basic ${c.req.query("auth_token")}`)
  return basicAuth({ username, password })(c, next)
}

The Authorization Effect layer (server.ts#L69-L83) only handles the basic scheme — no bearer branch exists.

Proposal

Add a new env var OPENCODE_SERVER_TOKEN that enables Bearer token auth:

# Option A: Bearer token only
OPENCODE_SERVER_TOKEN=my-secret-token

# Option B: Both schemes simultaneously (backward compatible)
OPENCODE_SERVER_PASSWORD=legacy-pass
OPENCODE_SERVER_TOKEN=my-secret-token

Expected behavior

Header Result
Authorization: Bearer <OPENCODE_SERVER_TOKEN> ✅ Authenticated
Authorization: Basic base64(user:OPENCODE_SERVER_PASSWORD) ✅ Authenticated (existing)
?auth_token=<OPENCODE_SERVER_TOKEN> ✅ Authenticated (query param)
No header, no token set ✅ Unsecured (existing)
Wrong token/password ❌ 401

Suggested middleware change

export const AuthMiddleware: MiddlewareHandler = (c, next) => {
  if (c.req.method === "OPTIONS") return next()

  const password = Flag.OPENCODE_SERVER_PASSWORD
  const token = Flag.OPENCODE_SERVER_TOKEN

  // No auth configured — pass through
  if (!password && !token) return next()

  const authHeader = c.req.header("authorization") ?? ""

  // Bearer token check
  if (token) {
    if (authHeader === `Bearer ${token}`) return next()
    if (c.req.query("auth_token") === token) return next()
  }

  // Fall back to Basic Auth
  if (password) {
    if (c.req.query("auth_token"))
      c.req.raw.headers.set("authorization", `Basic ${c.req.query("auth_token")}`)
    const username = Flag.OPENCODE_SERVER_USERNAME ?? "opencode"
    return basicAuth({ username, password })(c, next)
  }

  return c.text("Unauthorized", 401)
}

Changes needed

  1. Add OPENCODE_SERVER_TOKEN to flag.ts
  2. Update AuthMiddleware in middleware.ts to handle Bearer scheme
  3. Add bearer branch to the Effect-based Authorization layer in server.ts
  4. Update opencode attach --password to also accept --token flag
  5. Update the web command warning to mention both env vars

Alternatives Considered

  • Reuse OPENCODE_SERVER_PASSWORD as Bearer token — Conflates two auth schemes; clients can't know which header format to use.
  • Only support Bearer, drop Basic — Breaking change for existing deployments.
  • Reverse proxy workaround — Works but adds operational complexity for a common use case.

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Apr 29, 2026
  2. added a commit that references this issue on Apr 29, 2026
  3. removed
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on May 3, 2026
  4. github-actions commented on Jul 3, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions