Skip to main content
Blog

Your Login Page Might Not Actually Be Protecting Anything

April 28, 2026

AI coding tools skip login protections like security headers, cookie flags, and route-level auth. Here's what to check in your own app.

Your AI-built login page probably checks passwords and redirects users to a dashboard. That part works. The protections behind it (security headers, session cookie settings, and route-level auth checks) are the parts AI coding tools consistently leave out. Those gaps don't break the app, but they're what attackers look for once real users show up.

What "protecting" actually means

When a user logs in, several things should happen behind the scenes. The browser receives a session token (a small piece of data that proves the user is logged in). The server sends back response headers that tell the browser how to handle the connection. And every protected page checks whether the session is still valid before showing anything sensitive.

AI coding tools build the first part. The other parts often get skipped, not because the tools are broken, but because those protections aren't required for the app to work in development. They only matter once real people start using it.

Missing security headers

Security headers are response headers that tell browsers how to handle a connection safely. They prevent the page from being loaded inside a malicious frame, force HTTPS, and restrict where scripts can be loaded from.

In our audits of AI-built apps, the most common pattern is no security headers at all. No Content-Security-Policy, no Strict-Transport-Security, no X-Frame-Options, no X-Content-Type-Options. Insecure cookie configuration and missing protective headers fall under Security Misconfiguration, ranked in the OWASP Top 10 list of common web application risks.

Without these headers, your users are exposed to clickjacking (your login page loaded inside a malicious site to capture credentials), protocol downgrade attacks, and content-injection issues that the browser would otherwise block.

To check your own app: open developer tools, go to the Network tab, click any request, and look at the response headers. If you don't see headers like Content-Security-Policy, Strict-Transport-Security, and X-Frame-Options, your app isn't telling the browser how to protect the connection.

Session cookies without protective flags

When a user logs in, the app gives the browser a cookie that proves who they are. That cookie has three flags that prevent it from being stolen or misused. AI tools rarely set them.

HttpOnly tells the browser not to let JavaScript read the cookie. Without it, any script injection vulnerability anywhere in your app can read your users' login tokens and send them to an attacker.

Secure tells the browser to only send the cookie over encrypted connections. Without it, the login token can be sent over plain HTTP where anyone on the same network can read it.

SameSite tells the browser not to include the cookie when the request comes from a different website. Without it, a malicious page can make requests to your app that automatically carry the user's login cookie, letting the attacker take actions as that user.

To check this in your own app: open developer tools, go to the Application tab, and look at your cookies. Find the one that stores your session or auth token. The flags are listed in columns. HttpOnly, Secure, and SameSite should all be set.

A related pattern is even more exposed: storing login tokens in localStorage instead of cookies. Code like localStorage.setItem('token', jwt) puts the token somewhere any script on the page can read. There's no browser-level protection available for it.

Middleware as the only auth layer

A common pattern in AI-generated Next.js apps: middleware checks if the user is logged in before serving a page. If not, the user gets redirected to login. That part is correct.

The problem is that the actual pages and server functions behind the middleware don't check the session themselves. If anything bypasses the middleware, every page behind it serves whatever the visitor asks for.

This isn't theoretical. In March 2025, CVE-2025-29927 (severity 9.1 of 10) was disclosed in Next.js. Vercel's postmortem describes how a single HTTP header could bypass all middleware-based protections on self-hosted apps. One header, every protected page exposed.

The specific bug is patched, but the design problem stays. If your app relies on middleware alone for access control, a single future bypass reopens everything at once. The fix is to verify the user's session inside each protected route and server function, not only in the middleware layer.

You can check your code: open any route handler or server function behind a protected page and look for a session check. Something like getSession() or auth() called inside the route, not just in middleware.ts. If the only auth check is in middleware, your protection is one layer deep.

What to do about it

These three gaps are the default state of AI-generated authentication, not edge cases. Most fixes are straightforward:

  1. Add security headers. A few lines of configuration in your framework. Next.js supports them in next.config.ts. Similar options exist for other frameworks.
  2. Set cookie flags. Usually a one-line change wherever the auth cookie is set.
  3. Add route-level auth checks. More work than the others, but it's a pattern you apply once and reuse across protected routes and server actions.

The common thread: AI tools don't add these on their own. Each one requires someone to know the protection is needed and decide to add it. That's the gap to close before real users show up.

Frequently asked questions

Find out where your app stands

A fixed-price audit that covers security, code quality, and UX in one pass. Plain-language report, real evidence, prioritized fixes.

Get Your Audit