Files
webmail/lib/security/request-protocol.ts
T
lucamzanon a307859194 fix: derive the admin cookie's Secure flag from the request
The setup wizard and the admin sign-in set their session cookies by two
different rules. The wizard matches Secure to the request - X-Forwarded-
Proto from the proxy, else the URL scheme - because browsers drop Secure
cookies on plain HTTP and an unconditional Secure broke setup over HTTP.
The admin cookie kept `secure: NODE_ENV === 'production'`, so on the same
HTTP deployment the wizard worked and admin sign-in failed silently: the
cookie was set, the browser threw it away, every call came back 401.

Both now share one helper, lib/security/request-protocol.ts, and the admin
route passes its request in. Behind a TLS proxy that forwards the proto
nothing changes: the cookie is Secure as before. Callers that pass no
request keep the production default.
2026-09-19 11:19:35 +02:00

21 lines
716 B
TypeScript

/**
* Whether the browser reached us over HTTPS.
*
* The app itself only ever speaks plain HTTP: TLS terminates at the reverse
* proxy in front of it, which is expected to say so in `X-Forwarded-Proto`.
* Without a proxy the request URL's own scheme is the truth. Both the setup
* wizard and the admin session derive the cookie `Secure` flag from this, so
* the answer is the same for both.
*/
export function isHttpsRequest(request: Request): boolean {
const forwarded = request.headers.get('x-forwarded-proto');
if (forwarded) {
return forwarded.split(',')[0]!.trim().toLowerCase() === 'https';
}
try {
return new URL(request.url).protocol === 'https:';
} catch {
return false;
}
}