Fix auth token not persisting over HTTP (non-TLS) deployments (#47076)

<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #41641 & Resolves #44276

When Fleet is served over plain HTTP from a non-localhost host (e.g. a
Docker deployment accessed by IP), login fails with an "Authentication
Required" error.

To reproduce this, I ran the server as follows:

```
./build/fleet serve --dev --dev_license --server_tls=false --server_address=0.0.0.0:8080
```

And then, go to the Fleet UI using my private IP:

```
http://<my-lan-ip>:8080
```



https://github.com/user-attachments/assets/09543b9b-b9ee-4d1c-b47e-ebd49c20c699



The auth token is stored client-side in a `__Host-token` cookie with the
`Secure` attribute, and browsers silently drop `__Host-`/`Secure`
cookies on insecure, non-localhost origins. So, the token was never
persisted and the follow-up `GET /config` (and every subsequent request)
went out without it.

This change keeps the `__Host-token` + `Secure` cookie on HTTPS, and
falls back to a plain `token` cookie over HTTP so the token persists.
TL;DR: this restores the pre
[#40504](https://github.com/fleetdm/fleet/pull/40504) behavior for
non-TLS deployments and leaves HTTPS behavior unchanged.

# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.

## Testing

- [x] QA'd all new/changed functionality manually



https://github.com/user-attachments/assets/e7e838f3-f423-4e28-aebd-5f921af08b00




<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Fixed an issue where login requests would fail with an "Authentication
Required" error when Fleet is served over HTTP.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Nico
2026-06-08 11:45:51 -03:00
committed by GitHub
parent 4ce91c3a8b
commit bab14d7eb5
2 changed files with 19 additions and 5 deletions
@@ -0,0 +1 @@
- Fixed login failing with an "Authentication Required" error when Fleet is served over HTTP, by storing the auth token in a non-secure cookie outside of HTTPS contexts.
+18 -5
View File
@@ -6,23 +6,36 @@ import Cookie from "js-cookie";
const DEFAULT_EXPIRATION_DAYS = 5;
// The `__Host-` cookie name prefix and the `Secure` attribute both require the
// cookie to be set from a secure (HTTPS) context. When Fleet is served over
// plain HTTP (e.g. a Docker deployment without TLS), the browser silently
// refuses to store such a cookie, leaving the user unable to authenticate
// because the token is never persisted and therefore never attached to
// subsequent requests. Detect the context and fall back to a regular,
// non-secure cookie when not served over HTTPS.
const isSecure = (): boolean => window.location.protocol === "https:";
// `__Host-` prefixed names are only valid on secure cookies, so the cookie name
// must match the context it was stored in for get/remove to find it.
const getTokenName = (): string => (isSecure() ? "__Host-token" : "token");
const save = (token: string, expiresAt?: Date): void => {
Cookie.set("__Host-token", token, {
secure: true,
Cookie.set(getTokenName(), token, {
secure: isSecure(),
sameSite: "lax",
expires: expiresAt ?? DEFAULT_EXPIRATION_DAYS,
});
};
const get = (): string | null => {
return Cookie.get("__Host-token") || null;
return Cookie.get(getTokenName()) || null;
};
const remove = (): void => {
// NOTE: the secure and sameSite from the cookie must be provided
// to correctly remove. That is why we include the options here as well.
Cookie.remove("__Host-token", {
secure: true,
Cookie.remove(getTokenName(), {
secure: isSecure(),
sameSite: "lax",
});
};