Cursor auth not working: fixing login code the agent wired across files
Cursor's agent writes auth code it cannot fully see: .env files are on its default ignore list, so it guesses variable names, and it adds checks wherever the prompt pointed rather than everywhere data is read. Map every auth touchpoint, put the session check in one server-only helper, describe your env and Next.js version in a scoped rule, then review the diff with a deep review.
Symptom
Cursor is an editor, so unlike a hosted builder there is no platform setting to blame. The problem is in the code the agent wrote, usually spread across five to ten files. I describe the symptom here rather than quote an error, because most of these failures are silent.
Why it happens
The agent cannot read your environment files
Cursor's docs list .env* on the default ignore list, alongside lockfiles. Ignored files are blocked from Agent, Tab and @ mentions. That is a sensible security default, but it means the agent writes process.env.SOMETHING without being able to check the name against your real file. It will use whatever name its model expects for that library. Your .env.local may say something else.
The same docs warn that the terminal and MCP tools used by Agent cannot be blocked by .cursorignore. So the ignore list is a guard against accidental reading, not a vault.
It patches where you point it
Agent has no limit on tool calls and will happily edit many files, but it decides what to touch from your prompt and its search. Ask it to "protect the dashboard" and it may add a redirect in the dashboard layout. Next.js warns that layouts do not re-render on navigation and do not stop nested segments or Server Actions from running. The page is protected; the action behind its delete button is not.
It guesses your framework version
Supabase's Next.js guide says the session proxy file is proxy.ts on Next.js 16 and later, and that on Next.js 15 and earlier a proxy.ts file is never called. A model that defaults to the newer convention, working in an older project, writes a file that silently does nothing. Sessions then expire and users appear logged out.
Checkpoints are not version control
Cursor's checkpoints let you restore files to an earlier point, but the docs say they are stored locally, separate from Git, and restoring does not remove messages from the conversation. Roll back a failed auth refactor and the chat still describes code that no longer exists, so the next prompt builds on the wrong picture.
The fix
- Branch, then map every auth touchpoint yourself. Do not ask the agent to "fix auth" yet. Start from Git, and search:
git switch -c fix/auth
rg -n "use server|getSession|getUser|getClaims|auth\(\)|cookies\(\)" app lib src 2>/dev/null
rg -n "export (async )?function (middleware|proxy)" -g "*.ts"
grep '"next"' package.jsonYou now know every Server Action, every session read, which session file exists and which Next.js version you are on. If you would rather have Cursor do the mapping, switch to Plan Mode with Shift+Tab: its docs say it researches the codebase and produces a plan you edit before any code is written.
- Put the check in one server-only helper. Whatever the library, one function should answer "who is this, or send them to login". With Supabase:
// lib/auth/dal.ts
import "server-only";
import { cache } from "react";
import { redirect } from "next/navigation";
import { createClient } from "@/lib/supabase/server";
export const requireUser = cache(async () => {
const supabase = await createClient();
const { data, error } = await supabase.auth.getUser();
if (error || !data.user) redirect("/login");
return data.user;
});Then call it at the top of every page that reads private data, every Server Action and every Route Handler. Next.js describes Server Actions as needing the same care as public API endpoints, and its docs note that React's cache only deduplicates within a render, so actions and route handlers run the check every time, which is what you want.
// app/projects/actions.ts
"use server";
import { requireUser } from "@/lib/auth/dal";
import { deleteProjectForOwner } from "@/lib/db/projects";
export async function deleteProject(projectId: string) {
const user = await requireUser();
await deleteProjectForOwner({ projectId, ownerId: user.id }); // filter by owner in the query
}- Give the agent a file it can read instead of
.env. A typed env module documents every name, and the agent can see it:
// lib/env.server.ts
import "server-only";
import { z } from "zod"; // zod 4 syntax
export const env = z
.object({
NEXT_PUBLIC_SUPABASE_URL: z.url(),
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY: z.string().min(1),
// add server-only secrets here, with the exact names in your .env.local
})
.parse(process.env);Keep this server-only. Vercel's docs point out that NEXT_PUBLIC_ values are inlined at build time only when referenced by full name, so browser code should read process.env.NEXT_PUBLIC_SUPABASE_URL directly rather than through a parsed object.
-
Name the session file for your version. On Next.js 16 or later,
proxy.tsexportingproxy. On 15 or earlier,middleware.tsexportingmiddleware. Delete the other one so nobody edits a dead file. -
Write a scoped project rule. Cursor's rules docs say project rules live in
.cursor/rulesas.mdcfiles, and that a rule withglobsis attached automatically when a matching file is in context:
---
description: Auth and session rules for server code
globs: app/**/actions.ts, app/**/route.ts, app/**/page.tsx, lib/auth/**, proxy.ts, middleware.ts
alwaysApply: false
---
- This project uses Next.js 15. The session file is middleware.ts. Never create proxy.ts.
- Every Server Action and Route Handler starts with `await requireUser()` from @lib/auth/dal.ts.
- Read env names from @lib/env.server.ts. Do not invent new variable names.
- Never use getSession() for authorisation on the server.
- Filter every query by the current user's id.The docs add that @ file references in a rule are read when needed, not inlined, so keep the critical lines in the rule body.
-
Debug random logouts with evidence. Cursor's Debug Mode generates hypotheses, adds log statements, asks you to reproduce the bug, then makes a targeted fix and removes the instrumentation. That suits session timing bugs far better than another "fix the logout" prompt.
-
Review the whole diff, deeply. Run Agent Review from the Source Control tab to compare all local changes with your main branch. Its docs recommend the Deep level for security-sensitive code. Cursor also ships a
/review-securityskill for a dedicated security pass.
How to prevent it
- Ask for auth changes in Plan Mode, edit the plan so it lists every file, then build.
- Commit before each auth prompt. Use checkpoints for quick undo inside a session, Git for anything you might need tomorrow.
- Add
**/.envand**/.env.*to Cursor's global ignore list, as its docs suggest. The global list is empty by default and applies to every project. - Treat a passing login as the start of testing: try every protected URL and action while logged out, and as a second user.
My guide to fixing auth in AI-built apps covers sessions and row level security in more depth, and vibe coding security risks explains what an exposed action can cost. If the auth sprawl is part of a wider mess, read Cursor codebase messy.
When to get help
Auth that mostly works is the riskiest kind, because it passes a quick test. The free vibe code health check is a good first look. If you want someone to trace every route and action and fix them, a Rescue Sprint is a fixed-price audit and fix, usually about a week. The guide to fixing vibe-coded apps shows how auth fits with the other common failures.
- Cursor docs: Ignore file (.cursorignore and default ignore list), checked 9 November 2026
- Cursor docs: Agent overview (tools, checkpoints), checked 9 November 2026
- Cursor docs: Rules, checked 9 November 2026
- Cursor docs: Plan Mode, checked 9 November 2026
- Cursor docs: Debug Mode, checked 9 November 2026
- Cursor docs: Agent Review, checked 9 November 2026
- Cursor docs: Agent Skills (built-in skills), checked 9 November 2026
- Next.js docs: Authentication, checked 9 November 2026
- Supabase docs: Server-side auth for Next.js, checked 9 November 2026
- Vercel docs: Environment variables (troubleshooting), checked 9 November 2026
The vibe-code rescue checklist, as a PDF
About 40 checks across auth, data, payments, errors, mobile and secrets, on two pages.
Questions founders ask
Can Cursor's agent see my .env.local file?
Not through its file tools by default. Cursor's docs list .env* on the default ignore list, which blocks Agent, Tab and @ mentions. The docs also say the terminal and MCP tools cannot be blocked by .cursorignore.
Why are my Cursor project rules being ignored?
Project rules must be .mdc files in .cursor/rules. Cursor's docs say a plain .md file there is ignored, and a rule set to Apply Intelligently needs a description.
Is middleware enough to protect my pages?
No. Next.js says the proxy (formerly middleware) should not be the only line of defence. Check the session again in pages, Server Actions and Route Handlers that touch data.

Ant
Product designer who builds MVPs, based in Nottingham. 10+ years designing digital products, and the only person at BlackFig. More about me