> ## Content Index
> Fetch the complete content index at: https://debugly.dev/llms.txt
> Use this file to discover other available public pages before exploring further.

# ERR_TOO_MANY_REDIRECTS Only on the Login Page
- URL: https://debugly.dev/secure-cookie-http-login-redirect-loop/
- Published: 2026-09-24T07:30:00.000Z
- Updated: 2026-10-10T13:36:52.000Z
- Description: The login page redirected forever, and only over plaintext HTTP. The session cookie was created with the Secure flag, so the browser never stored it, the…
- Author: Rohit Bhadani
- Tags: Error Autopsy, Security, Web Development

The report said the login page was broken, and the screenshot showed the browser's redirect limit error, the loop where the login page sends you to login, forever. The unsettling detail was the selectivity: it reproduced on the staging URL served over plain HTTP, and never on production over HTTPS. A bug that exists only on the insecure origin is not a logic bug in the auth flow. It is the security configuration doing something the origin cannot support.

I keep a private list of these, because the incidents that hurt are always the ones somebody assumed were harmless.

The cookie was set with the Secure attribute. Over HTTPS that is correct and invisible. Over HTTP, the browser refuses to store a Secure cookie at all, so the session that the login just created is never sent back, the server sees an anonymous request, redirects to login, and the cycle repeats until the browser gives up. The loop is the security feature working, on an origin that cannot hold it.

This was a Node 22.14 app with a session cookie marked Secure and SameSite Lax, observed in Chrome 133 on an HTTP staging origin.

## The quick version

A Secure cookie is only stored and sent over HTTPS. When the application sets it on an HTTP origin, the write silently does nothing, the next request carries no session, the auth middleware redirects to login, the login succeeds and sets the cookie again, which again is not stored. Every step is individually correct, and the composition is an infinite loop with a redirect limit at the end.

The error message names the symptom, the loop, and hides the cause, which is a cookie that never persisted. This is the cookie version of an error describing the parser's confusion, per [error messages are a user interface](https://debugly.dev/error-messages-are-a-user-interface/).

## Why it is so hard to see

The defect is invisible in every place you would normally look. The login code ran and succeeded. The cookie was set, in the sense that the Set-Cookie header went out, which the server logs confirm. The browser's network tab shows the header present, which reads as the cookie working. The absence happens inside the browser's cookie store, which refuses the Secure cookie on an insecure origin, and that refusal is not loudly surfaced in the tools.

So the evidence says the cookie exists, twice, and the behaviour says it does not. The reconciliation is the Secure attribute plus the insecure origin, and the only tool that shows it plainly is the browser's cookie inspector, where the cookie is simply absent after the response that set it.

## The selectivity is the diagnosis

The bug's selectivity is its fingerprint and its lesson. It appears only where the origin is HTTP, which is why production was fine and staging was not, and why a developer on a localhost HTTPS setup could not reproduce it. Any auth bug that reproduces only on the insecure origin is a transport dependent cookie bug until proven otherwise, because the transport is the one variable that differs.

The same selectivity appears with the reverse misconfiguration, a cookie missing Secure on an HTTPS origin, which works everywhere and is silently sent over plaintext when any HTTP URL is ever hit, which is the confidentiality leak rather than the loop. Both are the attribute and the origin disagreeing, in opposite directions.

## The fix

**Serve the login flow over HTTPS everywhere it runs.** The durable fix is that there is no HTTP origin for the auth flow, including staging, because a staging origin over HTTP is precisely where the Secure cookie cannot live, and staging is where people test the flow. Staging over HTTPS with a real certificate removes the whole class, and the self signed or properly issued certificate on staging is a security feature, not a vanity.

**Fail loudly when the origin is insecure.** If an HTTP origin must exist for some reason, the application should detect that it is not behind TLS and refuse to run the auth flow, or log at error level on every Set-Cookie of a Secure cookie over a non TLS request. The silent no-op becomes a visible event, and the loop is caught at the first iteration instead of the fortieth.

**Set the attribute from the environment, deliberately.** The Secure flag should be a decision tied to the deployment's scheme, set explicitly in one place, so that a move between origins is a reviewed configuration change rather than an ambient mismatch. The one place is the same discipline as the allowlist in [SQL injection inside the ORM](https://debugly.dev/sql-injection-inside-an-orm/), where the security relevant choice lives in one reviewed location.

## The related traps in the same family

While fixing the loop, audit the neighbour attributes, because they produce sibling loops and leaks.

SameSite Lax with a cross site login flow can produce a loop for embeds and cross site redirects, because the cookie is not sent on the cross site hop, and the fix is understanding the flow's site boundaries rather than loosening the attribute.

A redirect that alternates between an HTTPS URL and an HTTP URL, usually from a misconfigured base URL, produces a loop where the cookie works on one hop and not the other, and the browser's redirect counter fills on the alternation. The open redirect audit in [the login redirect parameter](https://debugly.dev/open-redirect-in-the-login-flow/) catches the misconfigured base URL as part of its allowlist work.

## The rule

A Secure cookie on an HTTP origin is a session that is created and immediately forgotten, and the auth flow that depends on it becomes a redirect loop that every individual log line says is fine. Serve the auth flow over HTTPS on every environment, make the insecure origin loud instead of silent, and set the cookie attributes from one reviewed, environment aware place.

The loop is not the browser misbehaving. It is the browser honouring a security attribute more strictly than the deployment honours its own scheme, and between those two disagreements, the redirect counter is the only honest witness.