From 27704f962e018e9ca55e2b6d1b91c03858837264 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Aug 2026 23:52:46 -0700 Subject: [PATCH] Tweak: whitelist custom.css from auth (#6986) --- docs/configs/custom-css-js.md | 4 ++++ docs/installation/index.md | 2 +- src/middleware.js | 3 ++- src/middleware.test.js | 25 +++++++++++++++++++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/docs/configs/custom-css-js.md b/docs/configs/custom-css-js.md index a76ea6505..b198405d6 100644 --- a/docs/configs/custom-css-js.md +++ b/docs/configs/custom-css-js.md @@ -7,6 +7,10 @@ As of version v0.6.30 homepage supports adding your own custom css & javascript. To add custom css simply edit the `custom.css` file under your config directory, similarly for javascript you would edit `custom.js`. You can then target elements in homepage with various classes / ids to customize things to your liking. +!!! warning + + When Homepage authentication is enabled, `custom.css` remains publicly accessible so it can style the sign-in page. Do not include secrets or sensitive internal URLs in this file. `custom.js` remains protected and is only loaded after authentication. + You can also set a specific `id` for a service or bookmark to target with your custom css or javascript, e.g. ```yaml diff --git a/docs/installation/index.md b/docs/installation/index.md index 053d5cf73..d318f7649 100644 --- a/docs/installation/index.md +++ b/docs/installation/index.md @@ -74,6 +74,6 @@ For OIDC login (overrides password login): Homepage grants access to any identity that the configured OIDC provider authorizes for this client. Configure client assignments, groups, or access policies at the identity provider. Homepage does not apply additional claim-based authorization. -All app pages and `/api` routes except `/api/healthcheck` will require a signed-in session. Static assets remain public. +All app pages and `/api` routes except `/api/healthcheck` and `/api/config/custom.css` will require a signed-in session. Static assets remain public. Configure your OIDC provider with the a callback URI like `https://homepage.example.com/api/auth/callback/homepage-oidc`. diff --git a/src/middleware.js b/src/middleware.js index 1b1d66f58..d97e49320 100644 --- a/src/middleware.js +++ b/src/middleware.js @@ -33,7 +33,8 @@ export async function middleware(req) { } const pathname = new URL(req.url).pathname; - if (authEnabled && !pathname.startsWith("/api/healthcheck")) { + const isPublicAuthPath = pathname.startsWith("/api/healthcheck") || pathname === "/api/config/custom.css"; + if (authEnabled && !isPublicAuthPath) { // The MCP API handler authorizes both bearer tokens and Homepage sessions. if (pathname === "/api/mcp") { return withPrivateCache(NextResponse.next()); diff --git a/src/middleware.test.js b/src/middleware.test.js index aab97821a..532161ce2 100644 --- a/src/middleware.test.js +++ b/src/middleware.test.js @@ -100,6 +100,31 @@ describe("middleware", () => { expect(res.type).toBe("next"); }); + it("allows custom CSS without auth so it can style the signin page", async () => { + process.env.HOMEPAGE_AUTH_ENABLED = "true"; + process.env.HOMEPAGE_AUTH_SECRET = "secret"; + + const middleware = await loadMiddleware(); + const res = await middleware(createReq("localhost:3000", "http://localhost:3000/api/config/custom.css")); + + expect(getToken).not.toHaveBeenCalled(); + expect(NextResponse.next).toHaveBeenCalled(); + expect(res.type).toBe("next"); + }); + + it("continues to require auth for custom JavaScript", async () => { + process.env.HOMEPAGE_AUTH_ENABLED = "true"; + process.env.HOMEPAGE_AUTH_SECRET = "secret"; + + getToken.mockResolvedValueOnce(null); + + const middleware = await loadMiddleware(); + const res = await middleware(createReq("localhost:3000", "http://localhost:3000/api/config/custom.js")); + + expect(getToken).toHaveBeenCalled(); + expect(res.type).toBe("redirect"); + }); + it.each(["false", "0", "no", "off", ""])("treats HOMEPAGE_AUTH_ENABLED=%j as disabled", async (value) => { process.env.HOMEPAGE_AUTH_ENABLED = value;