diff --git a/changes/41641-token-not-being-passed-onto b/changes/41641-token-not-being-passed-onto new file mode 100644 index 0000000000..a4b3b0dfa8 --- /dev/null +++ b/changes/41641-token-not-being-passed-onto @@ -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. diff --git a/frontend/utilities/auth_token/index.ts b/frontend/utilities/auth_token/index.ts index f01848a82a..5749f0488f 100644 --- a/frontend/utilities/auth_token/index.ts +++ b/frontend/utilities/auth_token/index.ts @@ -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", }); };