From 8cbc43fbb006eadec8bf655150a7615f4559dd3e Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Sat, 9 May 2026 00:15:20 -0400 Subject: [PATCH] fix(server): include auth challenge on typed 401 (#26455) --- .../routes/instance/httpapi/middleware/authorization.ts | 9 +++++++-- .../opencode/test/server/httpapi-authorization.test.ts | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/opencode/src/server/routes/instance/httpapi/middleware/authorization.ts b/packages/opencode/src/server/routes/instance/httpapi/middleware/authorization.ts index 6f5648f30a..73676bd665 100644 --- a/packages/opencode/src/server/routes/instance/httpapi/middleware/authorization.ts +++ b/packages/opencode/src/server/routes/instance/httpapi/middleware/authorization.ts @@ -1,6 +1,6 @@ import { ServerAuth } from "@/server/auth" import { Effect, Encoding, Layer, Redacted } from "effect" -import { HttpRouter, HttpServerRequest, HttpServerResponse } from "effect/unstable/http" +import { HttpEffect, HttpRouter, HttpServerRequest, HttpServerResponse } from "effect/unstable/http" import { HttpApiError, HttpApiMiddleware } from "effect/unstable/httpapi" import { hasPtyConnectTicketURL } from "@/server/shared/pty-ticket" import { isPublicUIPath } from "@/server/shared/public-ui" @@ -33,7 +33,12 @@ function validateCredential( ) { return Effect.gen(function* () { if (!ServerAuth.required(config)) return yield* effect - if (!ServerAuth.authorized(credential, config)) return yield* new HttpApiError.Unauthorized({}) + if (!ServerAuth.authorized(credential, config)) { + yield* HttpEffect.appendPreResponseHandler((_request, response) => + Effect.succeed(HttpServerResponse.setHeader(response, "www-authenticate", WWW_AUTHENTICATE)), + ) + return yield* new HttpApiError.Unauthorized({}) + } return yield* effect }) } diff --git a/packages/opencode/test/server/httpapi-authorization.test.ts b/packages/opencode/test/server/httpapi-authorization.test.ts index 850098926a..e99a91e1d0 100644 --- a/packages/opencode/test/server/httpapi-authorization.test.ts +++ b/packages/opencode/test/server/httpapi-authorization.test.ts @@ -72,7 +72,9 @@ describe("HttpApi authorization middleware", () => { ) expect(missing.status).toBe(401) + expect(missing.headers["www-authenticate"] ?? "").toContain("Basic") expect(badPassword.status).toBe(401) + expect(badPassword.headers["www-authenticate"] ?? "").toContain("Basic") expect(good.status).toBe(200) }), )