[GH-ISSUE #3099] Blueprint auth.basic-auth labels override SSO priority, emit Basic challenge ahead of SSO redirect (regression) #17294

Open
opened 2026-05-18 17:47:05 -05:00 by GiteaMirror · 0 comments
Owner

Originally created by @strausmann on GitHub (May 17, 2026).
Original GitHub issue: https://github.com/fosrl/pangolin/issues/3099

Describe the Bug

When a public resource has both auth.sso-enabled=true and auth.basic-auth.user/password set via blueprint labels, Pangolin answers an unauthenticated request with HTTP 401 + WWW-Authenticate: Basic realm="pangolin" instead of issuing a 302 redirect to the SSO login page.

Result: browsers show the native Basic-Auth login dialog first, and only fall through to the SSO redirect (delivered in the HTML body) if the user clicks "Cancel" on the dialog. The intended UX is the opposite — SSO for browser users, Basic-Auth as a bypass for tooling/CI/curl.

The HTML response body still contains the SSO fallback, but the WWW-Authenticate header always wins in the browser, which makes the user-facing experience confusing on a resource that is explicitly configured to use SSO.

This behavior used to be SSO-priority earlier (Basic-Auth headers were accepted when the client proactively sent them, but no Basic challenge was emitted on no-auth requests). Filing this as a regression.

Environment

  • OS Type & Version: Ubuntu 24.04
  • Pangolin Version: 1.18.4
  • Gerbil Version: bundled with Pangolin 1.18.4
  • Traefik Version: 3.x (deployed alongside Pangolin)
  • Newt Version: 1.12.5
  • Olm Version: bundled with Pangolin 1.18.4

To Reproduce

  1. Deploy any HTTP service behind Newt in a Docker Compose stack.
  2. Attach the following labels to the proxied container (replace <key>, full-domain, port as appropriate):
labels:
  - "pangolin.public-resources.<key>.full-domain=example.com"
  - "pangolin.public-resources.<key>.protocol=http"
  - "pangolin.public-resources.<key>.ssl=true"
  - "pangolin.public-resources.<key>.targets[0].method=http"
  - "pangolin.public-resources.<key>.targets[0].port=8080"
  - "pangolin.public-resources.<key>.targets[0].path-match=prefix"
  - "pangolin.public-resources.<key>.auth.sso-enabled=true"
  - "pangolin.public-resources.<key>.auth.basic-auth.user=automation"
  - "pangolin.public-resources.<key>.auth.basic-auth.password=<random-32+ chars>"
  1. Restart pangolin-newt so the blueprint syncs.
  2. Verify the resource is healthy in the Pangolin dashboard (it is).
  3. Test:
    • curl -i https://example.com/ → returns HTTP 401 with WWW-Authenticate: Basic realm="pangolin". Body contains an SSO redirect fallback.
    • curl -i -u automation:<password> https://example.com/ → 200 OK (Basic-Auth bypass works).
    • Open https://example.com/ in a browser → native Basic-Auth dialog appears, not the SSO login page.

Same behavior when Header-Auth is set via the REST API (POST /v1/resource/{id}/header-auth) — but that variant is wiped on the next blueprint reconciliation, so blueprint labels are the only persistent option.

Expected Behavior

When both auth.sso-enabled=true and auth.basic-auth.* are set, SSO should be the primary auth path for browsers:

  • Unauthenticated request → 302 redirect to the SSO login page (current SSO-only behavior).
  • No WWW-Authenticate: Basic header in 401 responses, so browsers don't pop a Basic dialog ahead of the SSO redirect.
  • Pangolin still accepts requests that proactively include Authorization: Basic …, so tooling/CI/curl with a stored credential keeps working.

A minimal switch to control this (any of the following would solve it):

  • A label auth.basic-auth.challenge=false (default when SSO is also enabled) that suppresses the WWW-Authenticate header but keeps accepting incoming Basic credentials.
  • An implicit precedence rule: if auth.sso-enabled=true, do not emit WWW-Authenticate: Basic on no-auth responses.
  • A auth.basic-auth.mode label with values primary (current behavior) and bypass (proposed default).
Originally created by @strausmann on GitHub (May 17, 2026). Original GitHub issue: https://github.com/fosrl/pangolin/issues/3099 ## Describe the Bug When a public resource has both `auth.sso-enabled=true` and `auth.basic-auth.user/password` set via blueprint labels, Pangolin answers an unauthenticated request with `HTTP 401` + `WWW-Authenticate: Basic realm="pangolin"` instead of issuing a `302` redirect to the SSO login page. Result: browsers show the native Basic-Auth login dialog first, and only fall through to the SSO redirect (delivered in the HTML body) if the user clicks "Cancel" on the dialog. The intended UX is the opposite — SSO for browser users, Basic-Auth as a bypass for tooling/CI/curl. The HTML response body still contains the SSO fallback, but the `WWW-Authenticate` header always wins in the browser, which makes the user-facing experience confusing on a resource that is explicitly configured to use SSO. This behavior used to be SSO-priority earlier (Basic-Auth headers were accepted when the client proactively sent them, but no Basic challenge was emitted on no-auth requests). Filing this as a regression. ## Environment - OS Type & Version: Ubuntu 24.04 - Pangolin Version: 1.18.4 - Gerbil Version: bundled with Pangolin 1.18.4 - Traefik Version: 3.x (deployed alongside Pangolin) - Newt Version: 1.12.5 - Olm Version: bundled with Pangolin 1.18.4 ## To Reproduce 1. Deploy any HTTP service behind Newt in a Docker Compose stack. 2. Attach the following labels to the proxied container (replace `<key>`, `full-domain`, `port` as appropriate): ```yaml labels: - "pangolin.public-resources.<key>.full-domain=example.com" - "pangolin.public-resources.<key>.protocol=http" - "pangolin.public-resources.<key>.ssl=true" - "pangolin.public-resources.<key>.targets[0].method=http" - "pangolin.public-resources.<key>.targets[0].port=8080" - "pangolin.public-resources.<key>.targets[0].path-match=prefix" - "pangolin.public-resources.<key>.auth.sso-enabled=true" - "pangolin.public-resources.<key>.auth.basic-auth.user=automation" - "pangolin.public-resources.<key>.auth.basic-auth.password=<random-32+ chars>" ``` 3. Restart `pangolin-newt` so the blueprint syncs. 4. Verify the resource is healthy in the Pangolin dashboard (it is). 5. Test: - `curl -i https://example.com/` → returns `HTTP 401` with `WWW-Authenticate: Basic realm="pangolin"`. Body contains an SSO redirect fallback. - `curl -i -u automation:<password> https://example.com/` → 200 OK (Basic-Auth bypass works). - Open `https://example.com/` in a browser → native Basic-Auth dialog appears, not the SSO login page. Same behavior when Header-Auth is set via the REST API (`POST /v1/resource/{id}/header-auth`) — but that variant is wiped on the next blueprint reconciliation, so blueprint labels are the only persistent option. ## Expected Behavior When both `auth.sso-enabled=true` and `auth.basic-auth.*` are set, SSO should be the primary auth path for browsers: - Unauthenticated request → `302` redirect to the SSO login page (current SSO-only behavior). - No `WWW-Authenticate: Basic` header in 401 responses, so browsers don't pop a Basic dialog ahead of the SSO redirect. - Pangolin still accepts requests that proactively include `Authorization: Basic …`, so tooling/CI/curl with a stored credential keeps working. A minimal switch to control this (any of the following would solve it): - A label `auth.basic-auth.challenge=false` (default when SSO is also enabled) that suppresses the `WWW-Authenticate` header but keeps accepting incoming Basic credentials. - An implicit precedence rule: if `auth.sso-enabled=true`, do not emit `WWW-Authenticate: Basic` on no-auth responses. - A `auth.basic-auth.mode` label with values `primary` (current behavior) and `bypass` (proposed default).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/pangolin#17294