goauthentik / goauthentik/authentik

Proxy Provider form silently clears API-set cookie_domain on save (data loss in forward_single mode)

Open
#22,744 0 comments 1 reaction 1 assignee Claimed by @BeryJu View on GitHub
bug bug/confirmed
Dominant language
Python
Stars
25.6k
Forks
2k
Avg merge
1d 2h
Merged PRs (30d)
651

Description

### Describe the bug

The Proxy Provider edit form in the admin UI unconditionally clears cookie_domain to an empty string on every save for any
Provider whose mode is not forward_domain. The field is intentionally hidden in the UI for forward_single mode (and other
non-forward_domain modes), so operators have no visible cue that cookie_domain exists, that they hold a value, or that the
value is being cleared.

The wipe is performed in web/src/admin/providers/proxy/ProxyProviderForm.ts (lines 44–48 on tag version/2026.2.2, same
content on main HEAD):

async send(data: ProxyProvider): Promise {
data.mode = this.mode;
if (this.mode !== ProxyMode.ForwardDomain) {
data.cookieDomain = "";
}
// ...
}

cookieDomain is rendered only inside renderForwardDomainSettings() in ProxyProviderFormForm.ts (gated on mode ===
ProxyMode.ForwardDomain), so a forward_single operator never sees the field — but the API model accepts and stores
cookie_domain for any proxy mode. Provider records frequently carry meaningful cookie_domain values that were set via:

- Direct API calls (PATCH /api/v3/providers/proxy//)
- Blueprints
- Terraform / IaC tooling
- Bulk-provisioning scripts

For any such configuration, opening the Provider in the admin UI and clicking Update — even with no visible field changes —
silently destroys the stored value.

The decision to hide cookieDomain in the UI for non-forward_domain modes is a reasonable UX choice (it streamlines the form
for the dominant case). The data-loss behavior is not: the form is clearing a field it does not display, without warning,
on configuration the operator may not have set themselves and cannot see being cleared.

Operational impact in our deployment: 11 Proxy Providers, all in forward_single mode, all with cookie_domain=example.com
for cross-host SSO across *.example.com. After a single accidental UI save on any one Provider, that Provider's cookies
flip from Domain=example.com to host-only, breaking cross-host SSO for that subdomain until the value is restored via API
PATCH + authentik-server restart (the gorilla/sessions store doesn't rebuild on hot-reload — a separate operational quirk
we've worked around). We've written a periodic verification script that polls
/api/v3/providers/proxy/?cookie_domain__iexact= and exits non-zero when the count drops below expected, because we
couldn't detect the wipe any other way.

### How to reproduce

1. Create a Proxy Provider with mode=forward_single (any auth flow).
2. Set cookie_domain via API: PATCH /api/v3/providers/proxy// with body
{"cookie_domain":"example.com","mode":"forward_single"} (both fields required because DRF partial-update validation reads
request data, not merged state — omitting mode returns HTTP 400 with a misleading internal_host cannot be empty error).
3. Verify via GET /api/v3/providers/proxy// that cookie_domain is set.
4. Open the Provider in the admin UI: Admin → Applications → Providers → click the Provider name.
5. Click Update without changing any visible field.
6. Re-fetch via GET /api/v3/providers/proxy// — cookie_domain is now "".

### Expected behavior

API-set state on a hidden field should not be silently destroyed by a UI save that does not display the field. Three
reasonable resolution paths, picking is your call:

(a) Don't wipe what UI doesn't manage. When mode !== ProxyMode.ForwardDomain, preserve the stored cookie_domain rather than
overwriting it with "". The form simply doesn't touch the field. Smallest diff; matches the principle "form shouldn't
destroy fields it doesn't render."

(b) Expose cookieDomain in the UI for non-forward_domain modes. Render the field in forward_single (and other) modes — even
with helper text describing when it applies — so the operator sees what they're saving.

(c) Warn on save. Detect that stored cookie_domain is non-empty and is about to be cleared; show a confirmation dialog
before submit ("This will clear cookie_domain. Continue?").

(a) is the cheapest and most data-preserving; (b) is the most discoverable; (c) is the most explicit. We'd be happy with
any of the three.

### Screenshots

_No response_

### Additional context

- The wipe logic is unchanged on main HEAD as of the date of this filing — the bug is still present in the latest source.
Tag version/2026.2.2 and main are byte-identical for this file.
- The field's invisibility makes attribution hard: the only signal that a UI save destroyed configuration is downstream SSO
breakage at some-later-time on some-other-Provider. We worked around the diagnosis problem with a polling script
(referenced above); a fix removes the need.
- Mitigations we've adopted while waiting on a fix: (1) operational runbook entry instructing all Provider mutations to go
through the API, not the admin UI; (2) the polling script for drift detection.

### Deployment Method

Docker

### Version

2026.2.2

### Relevant log output

```shell

```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.