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

Open
opened 2026-06-22 02:56:19 -05:00 by GiteaMirror · 4 comments
Owner

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

Originally assigned to: @oschwartz10612 on GitHub.

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 Originally assigned to: @oschwartz10612 on GitHub. ## 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).
Author
Owner

@github-actions[bot] commented on GitHub (Jun 1, 2026):

This issue has been automatically marked as stale due to 14 days of inactivity. It will be closed in 14 days if no further activity occurs.

<!-- gh-comment-id:4588828578 --> @github-actions[bot] commented on GitHub (Jun 1, 2026): This issue has been automatically marked as stale due to 14 days of inactivity. It will be closed in 14 days if no further activity occurs.
Author
Owner

@strausmann commented on GitHub (Jun 1, 2026):

?

<!-- gh-comment-id:4589633098 --> @strausmann commented on GitHub (Jun 1, 2026): ?
Author
Owner

@AstralDestiny commented on GitHub (Jun 1, 2026):

Mmm should be a 307/308 but will poke the others.

<!-- gh-comment-id:4589700586 --> @AstralDestiny commented on GitHub (Jun 1, 2026): Mmm should be a 307/308 but will poke the others.
Author
Owner

@LaurenceJJones commented on GitHub (Jun 1, 2026):

This is hard to do as using basic auth AFAIK uses the traefik middleware under the hood so we cant control the ordering so ultimately this will trigger before the requests makes it to the pangolin dashboard.

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

Why? who says this should be so? there might be a user that wants the opposite we so cant really presume what somebody wants

Any reason you could just not use basic auth and just use a shared link instead using the access token approach? https://docs.pangolin.net/manage/access-control/links#use-the-access-token

<!-- gh-comment-id:4590946833 --> @LaurenceJJones commented on GitHub (Jun 1, 2026): This is hard to do as using basic auth AFAIK uses the traefik middleware under the hood so we cant control the ordering so ultimately this will trigger before the requests makes it to the pangolin dashboard. > When both auth.sso-enabled=true and auth.basic-auth.* are set, SSO should be the primary auth path for browsers: Why? who says this should be so? there might be a user that wants the opposite we so cant really presume what somebody wants Any reason you could just not use basic auth and just use a shared link instead using the access token approach? https://docs.pangolin.net/manage/access-control/links#use-the-access-token
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/pangolin#39107