fix(httpapi): add basic auth challenge for browser login

Adds a WWW-Authenticate challenge for unauthorized experimental HttpApi UI fallback responses so browsers open the Basic Auth prompt when a server password is configured.
This commit is contained in:
OpeOginni 2026-05-03 15:20:05 +02:00 committed by GitHub
parent 8433e8b433
commit 101566131d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 8 additions and 1 deletions

View file

@ -5,6 +5,7 @@ import { HttpApiError, HttpApiMiddleware, HttpApiSecurity } from "effect/unstabl
const AUTH_TOKEN_QUERY = "auth_token"
const UNAUTHORIZED = 401
const WWW_AUTHENTICATE = "Basic realm=\"Secure Area\""
export class Authorization extends HttpApiMiddleware.Service<Authorization>()(
"@opencode/ExperimentalHttpApiAuthorization",
@ -82,7 +83,12 @@ function validateRawCredential<A, E, R>(
) {
if (!isAuthRequired(config)) return effect
if (!isCredentialAuthorized(credential, config))
return Effect.succeed(HttpServerResponse.empty({ status: UNAUTHORIZED }))
return Effect.succeed(
HttpServerResponse.empty({
status: UNAUTHORIZED,
headers: { "www-authenticate": WWW_AUTHENTICATE },
}),
)
return effect
}

View file

@ -201,6 +201,7 @@ describe("HttpApi UI fallback", () => {
const response = await uiApp({ password: "secret", username: "opencode" }).request("/")
expect(response.status).toBe(401)
expect(response.headers.get("www-authenticate")).toBe('Basic realm="Secure Area"')
})
test("accepts auth token for the web UI", async () => {