What Vibe-Coded Apps Get Wrong About Authentication
91% of vibe-coded apps pass login checks but fail authorization. Learn the authentication gaps AI tools introduce and how to close each one before launch.
What vibe-coded apps get wrong about authentication is not the login form — it is everything that comes after it. Lovable, Bolt, Cursor, v0, and Replit all generate working login flows. Sessions get created. Tokens get verified. The user is authenticated. But the second half of the question — is this authenticated user allowed to access this specific resource? — gets systematically skipped. Every app that confirms a valid session without asking whether that session owns what it is requesting ships broken access control, regardless of how clean the login flow looks.
Q1 2026 research across vibe-coded apps found that 91.5% contain at least one critical vulnerability, and the leading category is authorization, not authentication. The distinction matters enormously for how you fix it: authentication vulnerabilities — weak JWT secrets, missing session expiry, insecure cookie flags — are caught by automated scanners. Authorization vulnerabilities — broken object-level authorization, privilege escalation via request body, missing row-level security — require behavioral testing against a running application with multiple user accounts. No scanner finds them automatically, and no AI tool generates them correctly by default.
This post covers the specific patterns AI-generated code produces that break authentication and authorization, why they appear consistently across every major vibe-coding tool, and what a review must test to close each gap. For the broader category, the vibe-coding security risks overview covers how these patterns compare across tools. The database layer — specifically why Supabase RLS gets disabled — is covered in the companion post on Supabase RLS security for AI-built apps.
Authentication vs. Authorization: Why AI Tools Nail One and Miss the Other
Authentication answers 'who are you?' Authorization answers 'what are you allowed to do?' Every major vibe-coding platform handles authentication by generating session middleware, token verification, and login/logout flows. The model has seen thousands of correct examples in its training data. It fills the pattern reliably.
Authorization is different. It requires context the model does not have: the schema that defines how users relate to resources, the business rules that govern which roles can access what, and the security principle that explicit denial should be the default for anything the policy does not cover. When a developer prompts 'build me an API route that returns a document by ID,' the model generates a route that fetches the document. The prompt did not say 'only return the document if the authenticated user owns it.' The model does not add that constraint unprompted, because the constraint was not in the specification. The route compiles. The test passes. The authorization check was never there.
Broken Object-Level Authorization: The Most Exploited Vibe-Coded Vulnerability
Broken Object-Level Authorization (BOLA), also called Insecure Direct Object Reference (IDOR) in older OWASP terminology, is the most prevalent access control vulnerability in AI-generated APIs. The pattern is consistent across tools: the route accepts a resource ID from the URL or request body, the session is verified, and the resource is returned — without confirming that the authenticated user owns or is permitted to access that specific record. Any authenticated user can substitute any ID in the request and receive data that belongs to any other user.
- →How it manifests: GET /api/documents/:id fetches the document matching the URL parameter. The route verifies the JWT. It does not add WHERE user_id = auth.uid() or any ownership filter. Any logged-in user can read any document by trying sequential or guessed IDs.
- →Why automated testing misses it: a scanner calling GET /api/documents/123 with valid credentials returns 200 and reports the endpoint as working. It does not test whether user B can retrieve user A's record by substituting the ID. BOLA requires a second test account and a deliberate cross-account request — behavioral testing, not scanning.
- →Scale of the problem: a 2026 analysis of 434 exploitable flaws in AI-generated apps found authorization and IDOR was the second-largest category with 88 confirmed vulnerabilities. Every app in that study was built with a vibe-coding tool using default prompts.
- →The fix: every database query that fetches, modifies, or deletes a record by ID must include an ownership filter reading the user's identity from the server-side session — never from the request body. WHERE id = $1 AND user_id = $2 where $2 is the authenticated user's ID from the verified token.
Session Management Failures in AI-Generated Applications
AI-generated session management skips controls that limit the damage a stolen credential can do. These are not missing features — they are absent properties on objects that already exist. They are easy to miss in code review because the session handling looks syntactically complete.
- →Missing session expiry: AI-generated cookie configurations frequently lack MaxAge or Expires. A session cookie with no expiry persists until the browser closes — and most modern browsers restore tabs on next open. Sessions last indefinitely, and a stolen cookie is valid forever.
- →Missing HttpOnly flag: without HttpOnly, the session cookie is readable via JavaScript. Any XSS vulnerability in the application — common in generated code that renders user-supplied content — allows an attacker to extract the session token with document.cookie.
- →Missing Secure flag: without Secure, the session cookie is transmitted over HTTP. Developers often forget to add the flag restriction after moving from http://localhost to production.
- →CSRF protection absent: AI-generated forms do not include CSRF tokens by default. Any route that accepts state-changing POST requests without CSRF verification is vulnerable to cross-site request forgery — an attacker's page can trigger authenticated actions on behalf of a logged-in user.
- →No logout invalidation: generated logout handlers often delete the client-side session without invalidating the server-side session record. The cookie is cleared in the browser, but the same token value remains valid on the server indefinitely.
JWT Vulnerabilities: Weak Secrets, Algorithm Confusion, and Missing Validation
JSON Web Tokens are the default authentication mechanism in nearly every vibe-coded application. They are also frequently misconfigured in predictable ways. JWT vulnerabilities in AI-generated code cluster around three failure modes: secrets taken from boilerplate examples, missing algorithm enforcement, and validation logic that trusts the token's own claims.
- →Weak secrets from tutorial boilerplate: generated code copies JWT signing secrets from documentation examples — 'your-secret-key', 'secret', 'jwt-secret'. These exact values appear in the model's training data. An attacker who can guess the secret can forge tokens with any user ID or role.
- →Missing algorithm enforcement: a JWT library that does not specify the accepted algorithm at verification may be vulnerable to algorithm confusion. The most dangerous variant allows sending a token signed with the 'none' algorithm, which bypasses signature verification under some library defaults. Generated jwt.verify() calls frequently omit the algorithms option.
- →Reading unvalidated claims: authorization logic that reads user.role or user.id directly from the decoded payload without cross-referencing the database trusts the token's own content. If the signing secret is weak enough to brute-force, an attacker can sign a modified token with elevated claims.
- →No expiry enforcement: some generated JWT handlers call jwt.decode() instead of jwt.verify(), or use libraries where expiry checking is opt-in. Expired tokens remain valid indefinitely if the exp claim is decoded but never checked against the current time.
Privilege Escalation via Request Body: How Generated APIs Leak Role Checks
A pattern closely related to BOLA is role escalation via client-supplied claims. Generated admin routes frequently derive authorization from data in the request — req.body.role, req.headers['x-user-role'], or a user object assembled from the request payload. Any logged-in user who adds role: 'admin' to their request body can access routes that trust that field without verifying it server-side.
- →The source of truth for identity is always the server: role, user ID, team membership, and permission levels must be read from the verified session token or a database lookup on the authenticated user's ID — never from request body fields, query parameters, or client-readable headers.
- →Generated middleware often reads but does not enforce: a common pattern is auth middleware that attaches a user object to the request if a session is found, then calls next() regardless of whether the session is valid. Protected routes that depend on req.user crash with a server error or, worse, treat undefined as 'access granted.'
- →Test every privileged route with a non-privileged account: make the direct API call with a standard-user session. If the response is anything other than 401 or 403, the authorization check is broken. Do not test through the UI — the UI hides admin routes while the underlying API routes remain accessible.
- →Next.js /api/admin/ routes: generated route handlers inside an admin path may rely entirely on middleware to gate access. If middleware can be bypassed by calling the route directly, changing the HTTP verb, or routing around the middleware chain, the handler runs without the auth check.
How to Test Authentication and Authorization in a Vibe-Coded App
Automated scans handle the surface layer: missing security headers, exposed paths, common injection patterns. DeployReady (npx deployready) gives you the automated baseline in minutes — security headers, OWASP Top 10 patterns, and a 0–100 readiness score. What it cannot do is test whether user B can read user A's data. That requires behavioral testing with two real accounts against the running application.
- →Create two test accounts with identical standard-user roles: user A and user B. Do not use your admin account for the comparison — it should have access to everything by design.
- →Map every resource type identified by an ID: documents, messages, profiles, orders, projects, settings — anything referenced by an ID in a URL or request body.
- →Attempt every operation as user B on user A's resources: GET /api/documents/[userA_id], PUT /api/documents/[userA_id], DELETE /api/documents/[userA_id]. Use curl or Burp Suite with user B's session cookie. Every 200 response where 403 is expected is a confirmed BOLA finding.
- →Test role escalation: make a direct API call to an admin endpoint with a standard-user session. Add role: 'admin' to the request body. Confirm the response is 401 or 403 in both cases.
- →Test session expiry: note the session cookie value after login. Wait past the expected expiry window. Make an authenticated request. Confirm it returns 401.
- →Test logout invalidation: record the session cookie before logout. Call the logout endpoint. Use the original cookie value on a subsequent authenticated request. Confirm it returns 401, not 200.
Frequently Asked Questions
What is the difference between authentication and authorization in a web app?
Authentication verifies identity — it confirms the person making a request is who they claim to be, typically via a session token, cookie, or JWT. Authorization verifies permission — it confirms the identified person is allowed to perform the specific action on the specific resource they are requesting. A user can be fully authenticated and still lack permission to access a particular document, admin route, or account setting. Most AI-generated code handles authentication correctly and skips or underimplements authorization.
What is BOLA and why is it so common in vibe-coded apps?
BOLA stands for Broken Object Level Authorization. It occurs when an API route fetches a resource by ID without verifying that the authenticated user owns or has permission to access that record. It is the most common access control vulnerability in AI-generated APIs because the prompt describing the route specifies what to return, not who is allowed to receive it. The model generates the fetch correctly and omits the ownership filter because the constraint was not in the specification. Any authenticated user can then access any record by substituting IDs in the request.
How do I check if my vibe-coded app has authorization vulnerabilities?
Create two test accounts with standard-user roles. Map every resource type in your application that is identified by an ID. Make direct API calls — not UI navigation — as user B attempting to read, modify, and delete user A's resources by substituting user A's IDs in the request. A 200 response where you expect 403 confirms broken object-level authorization. Also call admin endpoints directly with a standard-user session, including adding role: 'admin' to the request body. Automated scanners cannot run these tests — they require a second account and knowledge of your data schema.
Why do vibe-coded apps generate weak JWT secrets?
AI models generate JWT configuration by completing code patterns from training data. The most common JWT examples in tutorials and documentation use placeholder values like 'secret' or 'your-secret-key' to make examples runnable without setup. The model follows the most likely pattern it was trained on. JWT signing secrets must be cryptographically random, at least 256 bits long, and stored as environment variables — never written inline in source code.
Does Supabase RLS fix authorization vulnerabilities in vibe-coded apps?
Supabase Row Level Security is a database-layer control that prevents unauthorized data access at the query level, even if application code skips the ownership filter. It is one of the most important controls for Supabase-backed vibe-coded apps. But RLS must be enabled and correctly configured on every table, with policies that bind rows to auth.uid() — not just policies that check whether a user is logged in. AI tools frequently generate tables with RLS disabled, and policies generated by prompts sometimes skip ownership verification. RLS is a defense-in-depth layer, not a substitute for correct authorization logic in application code.
How Belsoft Helps Secure Vibe-Coded Applications
Belsoft runs security audits for teams that built with Lovable, Bolt, Cursor, v0, Replit, or any AI coding tool and need to confirm what is actually exposed before onboarding real users, responding to an enterprise security questionnaire, or making a customer-facing security commitment. The audit begins with DeployReady on the deployed URL — the automated baseline covering security headers, OWASP Top 10 patterns, and a 0–100 readiness score in minutes. The manual review that follows is what catches authorization vulnerabilities no scanner can find: every resource type tested cross-account, every role escalation path traced, JWT configuration reviewed for secrets and algorithm enforcement, session management verified for expiry and invalidation, and cookie flags checked across environments.
The result is a ranked list of confirmed findings with a fix recommendation for each, and a retest after your team implements the changes — closing the loop rather than shipping fixes you have not verified. Book a call at belsoftsolutions.com/meeting to scope the engagement, or visit our security audit service page for a full overview of what the audit covers.
“Authentication tells you who is knocking. Authorization decides whether to open the door. Vibe-coded apps nail the first and skip the second — and that is the gap every attacker walks through.”
Written by
Marco Silva
Security Engineer, Belsoft Solutions
More from the blog
Ready to partner?
Let's talk about your company.
30 minutes. No pitch. We talk through how you run today and where AI and automation would help.
Book a free audit
