Back to Explore
GuideVibeFix 编辑部Updated Oct 8, 2026

Don't Let AI Leave Your User System Unlocked: The 5-Piece Auth Playbook for Vibe Projects

AI writes login code fast and confidently — but auth is where it fails most: plaintext passwords, never-expiring JWTs, broken access control, secrets in frontend code. This playbook gives you five pieces: a build-vs-buy decision table, session mechanics, passwords and credentials, the authorization model, and hardening — plus a prompt template for AI-written auth and a 10-question review checklist.

Yellow 3D padlock with purple checkmark badge symbolizing secure authentication

Why auth is where AI fails hardest

Ask AI for a login feature and in 30 seconds you get the full set: signup form, login endpoint, JWT issuance — looks legit. But security researchers have long found that AI-generated authentication code is a vulnerability hotspot: passwords stored in plaintext, JWTs that never expire, password-reset links with no expiry, "remember me" as a plaintext token in frontend localStorage. Sneakier still are broken-access-control bugs — user A changes /users/123 to /users/124 in the URL and sees someone else's orders.

The root cause isn't that AI is dumb; it's that authentication has the widest gap between "looks like it works" and "actually secure." Broken CRUD shows up on screen instantly; broken auth works perfectly — the door is just unlocked — and you only find out on breach day. This guide splits login and permissions into five pieces, each with a clear line between "let AI do it" and "a human must personally sign off."

Piece 1: The build-vs-buy decision

The first decision is always: never roll your own crypto — but "writing your own auth flow" vs. "using a hosted service" is a separate question. The decision table:

Hosted (Clerk, Auth0, Supabase Auth): if your project needs any two of email/phone/social login, MFA, or organizations/teams — go hosted. The classic vibe-project profile — solo team, need speed, uncertain post-launch scale — makes hosted the default best answer. You pay tens of dollars a month to buy "never waking up at 3am to fix login." Supabase users get a natural bonus: Supabase Auth integrates natively with row-level security (RLS), so permission rules can live at the database layer.

Open-source self-hosted (Better Auth, Auth.js): when you're sensitive about data sovereignty, can predict user scale, or simply want the users table in your own hands. Better Auth has caught fire in vibe circles because its integrations with mainstream full-stack frameworks are "AI-friendly" — the code snippets in its docs run as-is, and AI rarely hallucinates its API.

Fully hand-rolled: valid in exactly one case — when your login flow is the product differentiator (e.g. Web3 wallet login, hardware-key-bound exotic flows). Otherwise, hand-rolled auth is the classic "reinvent the wheel, get free vulnerabilities" bundle.

The one-line rule: first ask "how many login methods do I need" — more than one, don't hand-roll; then ask "can user data leave the country" — if not, self-host open source. Write the conclusion in your README so future-you (and your AI) stop re-litigating it.

Piece 2: Session mechanics — JWT vs. session, settled once

This is where AI loves to hedge: "use JWT, it's modern and stateless." Don't buy it — it depends on context:

Browser web apps: prefer session cookies (httpOnly + Secure + SameSite). The argument is hard: httpOnly cookies are invisible to JS, so XSS can't steal the token; SameSite=Lax blocks most CSRF. JWT-in-localStorage is the most common security anti-pattern in vibe projects — one XSS hole anywhere on the page turns your users' tokens into an attacker's ATM. AI-generated code puts tokens in localStorage nine times out of ten because "it's elegant for frontend-backend separation" — elegance and security, pick one here.

Mobile apps / pure APIs / third-party integrations: short-lived JWT + refresh-token rotation. Access tokens expiring in 15 minutes, refresh tokens in secure storage (iOS Keychain / Android Keystore), old refresh token invalidated on each rotation. Even if an access token leaks, the attack window is 15 minutes.

Token lifetimes are a craft: access tokens short (minutes), refresh tokens medium (days, revocable), password-reset tokens single-use + 1-hour expiry, email-verification tokens 24-hour expiry. When having AI generate auth code, write "the lifetime of each token" into the requirements — otherwise it defaults to "never expires," the single most common hole in AI-written auth code.

Piece 3: Passwords and credentials — three iron laws

Password handling has exactly three iron laws; breaking any one is a P0 incident:

Law 1: store only hashes, argon2id or bcrypt, never invent your own algorithm. When having AI write it, specify the algorithm and parameters explicitly (e.g. argon2id, 64MB memory, 3 iterations) — otherwise you may get salted MD5. In 2026, MD5 brute-forcing is a seconds-scale affair. Bonus: validate password strength with a library like zxcvbn, not a hand-rolled "must contain upper+lower+digit+symbol" regex — that's a 2010 practice with terrible UX.

Law 2: every secret lives only in server-side environment variables. JWT signing keys, OAuth client secrets, database passwords — any secret appearing in frontend code, the git repo, or AI chat logs counts as leaked. The iron law for AI: it reads process.env; it never writes a key into any file. Before launch, self-audit at the level of git log -p | grep -i secret, or just run gitleaks across the repo.

Law 3: password-reset flows use single-use tokens + short expiry + burn-after-use. AI-generated reset flows make three classic mistakes: reset links that never expire, predictable tokens tied to user id (like /reset?userId=123), and old tokens still working after a successful reset. Correct: cryptographically random token (32+ bytes), 1-hour expiry, invalidated on use, and invalidate all of the user's sessions after a successful reset (so an attacker can't linger on an old session).

Piece 4: The authorization model — authentication is "who you are," authorization is "what you can do"

Many vibe projects die treating "logged in" as "authorized." Starting with RBAC (role-based access control) is enough, but there are three places AI will definitely miss:

Miss 1: resource-level checks — "only your own data." This is IDOR's killing field. AI's GET /api/orders/:id is typically "fetch the order and return it," never "and the order belongs to the current user." The fix: every resource endpoint carries an ownership check — or go further and push the rules into the data layer with database RLS (Supabase/Postgres), so even a leaky API layer gets stopped at the database. Adding "all resource endpoints must verify resource ownership" to your requirements blocks 90% of IDOR.

Miss 2: don't hardcode the admin backdoor. AI loves if (user.email === 'admin@xxx.com') allow. Correct: a role column plus middleware like requireRole('admin'). Separate deployment, separate domain, IP allowlist or VPN for the admin panel — bonus points.

Miss 3: audit-log permission changes. Who made whom an admin, who exported the full user table — log these as append-only records. Not to catch insiders; to answer "what's the blast radius" when something breaks. Vibe projects can do it lightly: one audit_logs table, inserts only, archived periodically.

Piece 5: Hardening — the login endpoint is the attacker's front door

Login, signup, and password-reset are the most-scanned endpoints on any site. The hardening checklist:

Anti-brute-force: rate-limit login (e.g. 5/min per IP, 10/10min per account); on exceeding, add a captcha instead of locking the account (account lockout gets weaponized to lock out other people's accounts). When AI writes the rate-limit middleware, remind it to count in Redis with a sliding window — not an in-memory Map (per-instance memory counters don't coordinate across deployments).

Anti-enumeration: "email not registered" and "wrong password" must return identical error messages and response times. A helpful "user doesn't exist" is a free oracle for attackers validating email lists. Same for signup: blur the "already registered" response ("if the email exists, a verification mail was sent").

OAuth CSRF protection: the state parameter must be randomly generated, stored in the session, and validated on callback. When AI wires up GitHub/Google login, eight times out of ten the state is a hardcoded string or omitted entirely — the most common real-world vulnerability in OAuth flows.

Log redaction: login logs record who, when, from which IP, success or not — never passwords, tokens, or full phone numbers. Iron law for AI-written logging code: credential-class fields get truncated to last-four or fully masked in logs.

The AI prompt template + the human 10-question review checklist

Two copy-paste tools to close. First, the prompt template for having AI build auth (works with any agent):

Implement email+password login. Requirements: 1) passwords hashed with argon2id; 2) sessions via httpOnly + Secure + SameSite=Lax session cookies, no tokens in localStorage; 3) access tokens expire in 15 minutes; 4) every resource endpoint must verify the resource belongs to the current user; 5) rate-limit login (5/min per IP); 6) uniform error messages on login failure — never distinguish "user not found" from "wrong password"; 7) all secrets from environment variables, never written into code. Output the design first (schema + endpoint list + token lifetimes); write code only after I approve.

The last sentence is the key: make AI output the design before the code. For a module like auth, design review is worth ten times code review — get the schema wrong and everything after is patches.

The 10 questions a human must personally clear: are passwords hashed (check the migration, not the code)? Are token lifetimes minutes, not years? Are there secrets in the repo (run gitleaks)? Can I see someone else's data by editing the id in the URL (try it by hand)? Are login-failure messages uniform? Is OAuth state validated? Does the admin panel have independent role checks? Do reset links burn after one use? Are there plaintext credentials in logs? Do old sessions die after password change / account deletion?

Each of these ten is a hole that caused a real P0 somewhere. Vibe coding's speed advantage shouldn't be built on an unlocked door — auth is the one module where "slow is fast": two hours with this checklist before launch saves the 3am incident call.

Browse projectsPublish your project

Related articles

A hand holding a smartphone with multiple app notifications popping up on screen, next to a bell icon
Guide
Your Users Won't Open Your Site Every Day: A Hands-On Notification System Guide for Vibe-Coded Projects

Getting signups is only the start — users churn by day 3 and you have no horn to call them back. This guide covers notification systems for vibe projects: channel selection, email with Resend from day one, SPF/DKIM/DMARC done right, when SMS is worth the money, frequency caps and unsubscribe, retries and dead letters, plus a launch acceptance checklist.

Backend EngineeringAutomationDeveloper Workflow
JavaScript fetch POST request code on an API documentation interface
Guide
Let the Outside World Knock: Webhook Integration in Practice for Vibe Projects

A user just paid — how does your system know? Code was pushed to GitHub — how does deployment trigger itself? The answer is webhooks: APIs called in reverse. This guide breaks webhook integration into five pieces — receiver design, signature verification, idempotency, retries and dead letters, local debugging — walks you through complete Stripe and GitHub flows, and flags the three traps AI loves to fall into.

API IntegrationAutomationBackend Engineering